@onehat/data 1.4.5 → 1.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -372,6 +372,19 @@ describe('Repository Base', function() {
372
372
  expect(didFireChangeFilters).to.be.true;
373
373
  });
374
374
 
375
+ it('changing filters resets pagination', function() {
376
+ this.repository.isPaginated = true;
377
+ this.repository.setPageSize(1);
378
+ this.repository.setPage(3);
379
+
380
+ this.repository.setFilters({
381
+ b: '1',
382
+ c: '2',
383
+ });
384
+
385
+ expect(this.repository.page).to.be.eq(1);
386
+ });
387
+
375
388
  });
376
389
 
377
390
  describe('pagination', function() {
@@ -414,29 +427,73 @@ describe('Repository Base', function() {
414
427
  });
415
428
 
416
429
  it('_calculatePaginationVars', function() {
417
- let results = this.Repository._calculatePaginationVars(15, 1, 10), // Capital "R"
418
- expected = {
419
- page: 1,
420
- pageSize: 10,
421
- total: 15,
422
- totalPages: 2,
423
- pageStart: 1,
424
- pageEnd: 10,
425
- pageTotal: 10,
426
- };
427
- expect(_.isEqual(results, expected)).to.be.true;
428
-
429
- results = this.Repository._calculatePaginationVars(15, 2, 10); // Capital "R"
430
- expected = {
431
- page: 2,
432
- pageSize: 10,
433
- total: 15,
434
- totalPages: 2,
435
- pageStart: 11,
436
- pageEnd: 15,
437
- pageTotal: 5,
438
- };
439
- expect(_.isEqual(results, expected)).to.be.true;
430
+ let results;
431
+
432
+ results = this.Repository._calculatePaginationVars(0, 1, 10);
433
+ expect(results.page).to.be.eq(1);
434
+ expect(results.pageSize).to.be.eq(10);
435
+ expect(results.total).to.be.eq(0);
436
+ expect(results.totalPages).to.be.eq(1);
437
+ expect(results.pageStart).to.be.eq(0);
438
+ expect(results.pageEnd).to.be.eq(0);
439
+ expect(results.pageTotal).to.be.eq(0);
440
+
441
+ results = this.Repository._calculatePaginationVars(15, 1, 10);
442
+ expect(results.page).to.be.eq(1);
443
+ expect(results.pageSize).to.be.eq(10);
444
+ expect(results.total).to.be.eq(15);
445
+ expect(results.totalPages).to.be.eq(2);
446
+ expect(results.pageStart).to.be.eq(1);
447
+ expect(results.pageEnd).to.be.eq(10);
448
+ expect(results.pageTotal).to.be.eq(10);
449
+
450
+ results = this.Repository._calculatePaginationVars(15, 2, 10);
451
+ expect(results.page).to.be.eq(2);
452
+ expect(results.pageSize).to.be.eq(10);
453
+ expect(results.total).to.be.eq(15);
454
+ expect(results.totalPages).to.be.eq(2);
455
+ expect(results.pageStart).to.be.eq(11);
456
+ expect(results.pageEnd).to.be.eq(15);
457
+ expect(results.pageTotal).to.be.eq(5);
458
+
459
+ results = this.Repository._calculatePaginationVars(15, 2, 5);
460
+ expect(results.page).to.be.eq(2);
461
+ expect(results.pageSize).to.be.eq(5);
462
+ expect(results.total).to.be.eq(15);
463
+ expect(results.totalPages).to.be.eq(3);
464
+ expect(results.pageStart).to.be.eq(6);
465
+ expect(results.pageEnd).to.be.eq(10);
466
+ expect(results.pageTotal).to.be.eq(5);
467
+
468
+ results = this.Repository._calculatePaginationVars(7, 2, 5);
469
+ expect(results.page).to.be.eq(2);
470
+ expect(results.pageSize).to.be.eq(5);
471
+ expect(results.total).to.be.eq(7);
472
+ expect(results.totalPages).to.be.eq(2);
473
+ expect(results.pageStart).to.be.eq(6);
474
+ expect(results.pageEnd).to.be.eq(7);
475
+ expect(results.pageTotal).to.be.eq(2);
476
+
477
+ results = this.Repository._calculatePaginationVars(15, 15, 1);
478
+ expect(results.page).to.be.eq(15);
479
+ expect(results.pageSize).to.be.eq(1);
480
+ expect(results.total).to.be.eq(15);
481
+ expect(results.totalPages).to.be.eq(15);
482
+ expect(results.pageStart).to.be.eq(15);
483
+ expect(results.pageEnd).to.be.eq(15);
484
+ expect(results.pageTotal).to.be.eq(1);
485
+ });
486
+
487
+ it('reset pagination', function() {
488
+ expect(this.repository.page).to.be.eq(1);
489
+
490
+ this.repository.isPaginated = true;
491
+ this.repository.setPageSize(1);
492
+ this.repository.setPage(3);
493
+ expect(this.repository.page).to.be.eq(3);
494
+
495
+ this.repository.resetPagination();
496
+ expect(this.repository.page).to.be.eq(1);
440
497
  });
441
498
 
442
499
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/data",
3
- "version": "1.4.5",
3
+ "version": "1.4.9",
4
4
  "description": "JS data modeling package with adapters for many storage mediums.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -1,7 +1,12 @@
1
+ /**
2
+ * This file is categorized as "Proprietary Framework Code"
3
+ * and is subject to the terms and conditions defined in
4
+ * file 'LICENSE.txt', which is part of this source code package.
5
+ */
1
6
  /** @module Repository */
2
7
 
3
8
  import OfflineRepository from '@onehat/data/src/Repository/Offline.js';
4
- import AsyncStorage from '@react-native-community/async-storage';
9
+ import AsyncStorage from '@react-native-async-storage/async-storage';
5
10
  import _ from 'lodash';
6
11
 
7
12
  /**
@@ -37,10 +42,12 @@ class AsyncStorageRepository extends OfflineRepository {
37
42
  value = result; // Invalid JSON, just return raw result
38
43
  }
39
44
  }
45
+
40
46
  return value;
41
47
  } catch (error) {
42
48
  if (this.debugMode) {
43
49
  const msg = error && error.message;
50
+ console.log('_storageGetValue error', msg);
44
51
  debugger;
45
52
  }
46
53
  }
@@ -60,7 +67,7 @@ class AsyncStorageRepository extends OfflineRepository {
60
67
  const results = await AsyncStorage.multiGet(this._namespace(keys));
61
68
 
62
69
  if (this.debugMode) {
63
- console.log(this.name, 'AsyncStorage.multiGet results', name, results);
70
+ console.log(this.name, 'AsyncStorage.multiGet results', results);
64
71
  }
65
72
 
66
73
  let values = [];
@@ -72,7 +79,17 @@ class AsyncStorageRepository extends OfflineRepository {
72
79
  } catch (e) {
73
80
  parsed = value; // Invalid JSON, just return raw result
74
81
  }
75
- values.push(parsed);
82
+ if (parsed === null) {
83
+ // Values should be stored as JSON, so it should be either {} or []. If it's null, that means the AsyncStorage can't find the record
84
+ // Delete the index to this record
85
+ const re = new RegExp('^' + this.name + '\-' + '(.*)'),
86
+ matches = key.match(re);
87
+ debugger;
88
+ const id = parseInt(matches, 10);
89
+ this._deleteFromIndex(id);
90
+ } else {
91
+ values.push(parsed);
92
+ }
76
93
  })
77
94
  }
78
95
 
@@ -84,6 +101,7 @@ class AsyncStorageRepository extends OfflineRepository {
84
101
  } catch (error) {
85
102
  if (this.debugMode) {
86
103
  const msg = error && error.message;
104
+ console.log('_storageGetMultiple error', msg);
87
105
  debugger;
88
106
  }
89
107
  }
@@ -103,6 +121,7 @@ class AsyncStorageRepository extends OfflineRepository {
103
121
  } catch (error) {
104
122
  if (this.debugMode) {
105
123
  const msg = error && error.message;
124
+ console.log('_storageSetValue error', msg);
106
125
  debugger;
107
126
  }
108
127
  }
@@ -126,11 +145,16 @@ class AsyncStorageRepository extends OfflineRepository {
126
145
  console.log(this.name, 'AsyncStorage.multiSet', keys);
127
146
  }
128
147
 
148
+ if (_.isEmpty(converted)) {
149
+ return;
150
+ }
151
+
129
152
  return await AsyncStorage.multiSet(converted);
130
153
 
131
154
  } catch (error) {
132
155
  if (this.debugMode) {
133
156
  const msg = error && error.message;
157
+ console.log('_storageSetMultiple error', msg);
134
158
  debugger;
135
159
  }
136
160
  }
@@ -151,6 +175,7 @@ class AsyncStorageRepository extends OfflineRepository {
151
175
  } catch (error) {
152
176
  if (this.debugMode) {
153
177
  const msg = error && error.message;
178
+ console.log('_storageDeleteValue error', msg);
154
179
  debugger;
155
180
  }
156
181
  }
@@ -171,6 +196,7 @@ class AsyncStorageRepository extends OfflineRepository {
171
196
  } catch (error) {
172
197
  if (this.debugMode) {
173
198
  const msg = error && error.message;
199
+ console.log('_storageDeleteMultiple error', msg);
174
200
  debugger;
175
201
  }
176
202
  }
@@ -1,94 +1,99 @@
1
- import OfflineRepository from '@onehat/data/src/Repository/Offline';
2
- import * as SecureStore from 'expo-secure-store'; // see: https://docs.expo.io/versions/latest/sdk/securestore/
3
- import _ from 'lodash';
4
-
5
1
  /**
6
- * Repository representing Expo's SecureStore
7
- * Uses expo-secure-store package
2
+ * This file is categorized as "Proprietary Framework Code"
3
+ * and is subject to the terms and conditions defined in
4
+ * file 'LICENSE.txt', which is part of this source code package.
8
5
  */
9
- class SecureStoreRepository extends OfflineRepository {
10
-
11
- constructor(config = {}) {
12
- super(...arguments);
13
- _.merge(this, config);
14
- }
15
-
16
- _storageGetValue = async (name) => {
17
- try {
18
-
19
- if (this.debugMode) {
20
- console.log(this.name, 'SecureStore.get', name);
21
- }
22
-
23
- const result = await SecureStore.getItemAsync(this._namespace(name));
24
-
25
- if (this.debugMode) {
26
- console.log(this.name, 'SecureStore.get results', name, result);
27
- }
28
-
29
- let value;
30
- if (!_.isNil(result)) {
31
- try {
32
- value = JSON.parse(result);
33
- } catch (e) {
34
- value = result; // Invalid JSON, just return raw result
35
- }
36
- }
37
- return value;
38
- } catch (error) {
39
- if (this.debugMode) {
40
- const msg = error && error.message;
41
- debugger;
42
- }
43
- }
44
- }
45
-
46
- _storageSetValue = async (name, value) => {
47
- try {
48
- if (!_.isString(value)) {
49
- value = JSON.stringify(value);
50
- }
51
- if (this.debugMode) {
52
- console.log(this.name, 'SecureStore.set', name, value);
53
- }
54
-
55
- const result = await SecureStore.setItemAsync(this._namespace(name), value);
56
-
57
- // if (this.debugMode) {
58
- // console.log(this.name, 'SecureStore.set results', name, result);
59
- // }
60
- return result;
61
- } catch (error) {
62
- if (this.debugMode) {
63
- const msg = error && error.message;
64
- debugger;
65
- }
66
- }
67
- }
68
-
69
- _storageDeleteValue = async (name) => {
70
- try {
71
- if (this.debugMode) {
72
- console.log(this.name, 'SecureStore.delete', name);
73
- }
74
-
75
- const result = await SecureStore.deleteItemAsync(this._namespace(name));
76
-
77
- // if (this.debugMode) {
78
- // console.log(this.name, 'SecureStore.delete results', name, result);
79
- // }
80
- return result;
81
- } catch (error) {
82
- if (this.debugMode) {
83
- const msg = error && error.message;
84
- debugger;
85
- }
86
- }
87
- }
88
-
89
- };
90
-
91
- SecureStoreRepository.className = 'SecureStore';
92
- SecureStoreRepository.type = 'secure';
93
-
94
- export default SecureStoreRepository;
6
+ import OfflineRepository from '@onehat/data/src/Repository/Offline.js';
7
+ import * as SecureStore from 'expo-secure-store'; // see: https://docs.expo.io/versions/latest/sdk/securestore/
8
+ import _ from 'lodash';
9
+
10
+ /**
11
+ * Repository representing Expo's SecureStore
12
+ * Uses expo-secure-store package
13
+ */
14
+ class SecureStoreRepository extends OfflineRepository {
15
+
16
+ constructor(config = {}) {
17
+ super(...arguments);
18
+ _.merge(this, config);
19
+ }
20
+
21
+ _storageGetValue = async (name) => {
22
+ try {
23
+
24
+ if (this.debugMode) {
25
+ console.log(this.name, 'SecureStore.get', name);
26
+ }
27
+
28
+ const result = await SecureStore.getItemAsync(this._namespace(name));
29
+
30
+ if (this.debugMode) {
31
+ console.log(this.name, 'SecureStore.get results', name, result);
32
+ }
33
+
34
+ let value;
35
+ if (!_.isNil(result)) {
36
+ try {
37
+ value = JSON.parse(result);
38
+ } catch (e) {
39
+ value = result; // Invalid JSON, just return raw result
40
+ }
41
+ }
42
+ return value;
43
+ } catch (error) {
44
+ if (this.debugMode) {
45
+ const msg = error && error.message;
46
+ debugger;
47
+ }
48
+ }
49
+ }
50
+
51
+ _storageSetValue = async (name, value) => {
52
+ try {
53
+ if (!_.isString(value)) {
54
+ value = JSON.stringify(value);
55
+ }
56
+ if (this.debugMode) {
57
+ console.log(this.name, 'SecureStore.set', name, value);
58
+ }
59
+
60
+ const result = await SecureStore.setItemAsync(this._namespace(name), value);
61
+
62
+ // if (this.debugMode) {
63
+ // console.log(this.name, 'SecureStore.set results', name, result);
64
+ // }
65
+ return result;
66
+ } catch (error) {
67
+ if (this.debugMode) {
68
+ const msg = error && error.message;
69
+ debugger;
70
+ }
71
+ }
72
+ }
73
+
74
+ _storageDeleteValue = async (name) => {
75
+ try {
76
+ if (this.debugMode) {
77
+ console.log(this.name, 'SecureStore.delete', name);
78
+ }
79
+
80
+ const result = await SecureStore.deleteItemAsync(this._namespace(name));
81
+
82
+ // if (this.debugMode) {
83
+ // console.log(this.name, 'SecureStore.delete results', name, result);
84
+ // }
85
+ return result;
86
+ } catch (error) {
87
+ if (this.debugMode) {
88
+ const msg = error && error.message;
89
+ debugger;
90
+ }
91
+ }
92
+ }
93
+
94
+ };
95
+
96
+ SecureStoreRepository.className = 'SecureStore';
97
+ SecureStoreRepository.type = 'secure';
98
+
99
+ export default SecureStoreRepository;
@@ -292,8 +292,8 @@ class AjaxRepository extends Repository {
292
292
  */
293
293
  _onChangeSorters = () => {
294
294
  const sorter = this.sorters[0];
295
- this.setParam(this.paramSort, sorter.name);
296
- this.setParam(this.paramDirection, sorter.direction);
295
+ this.setParam(this.paramSort, sorter.name, true); // true to set baseParam
296
+ this.setParam(this.paramDirection, sorter.direction, true);
297
297
 
298
298
  if (this.isLoaded) {
299
299
  return this.reload();
@@ -319,8 +319,8 @@ class AjaxRepository extends Repository {
319
319
  * Refreshes entities.
320
320
  */
321
321
  _onChangePagination = () => {
322
- this.setParam(this.paramPageNum, this.page);
323
- this.setParam(this.paramPageSize, this.pageSize);
322
+ this.setParam(this.paramPageNum, this.page, true); // true to set baseParam
323
+ this.setParam(this.paramPageSize, this.pageSize, true);
324
324
 
325
325
  if (this.isLoaded) {
326
326
  return this.reload();
@@ -23,13 +23,8 @@ class OfflineRepository extends MemoryRepository {
23
23
 
24
24
  async initialize() {
25
25
  this.pauseEvents(); // Queue 'initialize' event from super
26
- await super.initialize();
27
26
 
28
- this._index = await this._getIndex();
29
- if (!this._index) {
30
- await this._setIndex([]);
31
- this._index = [];
32
- }
27
+ await super.initialize(); // Initializes index in _loadFromStorage()
33
28
 
34
29
  this.resumeEvents(true); // Now fire it!
35
30
  }
@@ -80,7 +75,14 @@ class OfflineRepository extends MemoryRepository {
80
75
  */
81
76
  _loadFromStorage = async () => {
82
77
  try {
83
- const ids = await this._getIndex(),
78
+
79
+ this._index = await this._getIndex();
80
+ if (!this._index) {
81
+ await this._setIndex([]);
82
+ this._index = [];
83
+ }
84
+
85
+ const ids = this._index,
84
86
  total = ids && ids.length ? ids.length : 0,
85
87
  results = [];
86
88
 
@@ -648,6 +648,7 @@ export default class Repository extends EventEmitter {
648
648
  if (!_.isEqual(this.filters, filters)) {
649
649
  isChanged = true;
650
650
  this.filters = filters;
651
+ this.resetPagination();
651
652
  this.emit('changeFilters');
652
653
  if (this._onChangeFilters) {
653
654
  return this._onChangeFilters();
@@ -666,6 +667,17 @@ export default class Repository extends EventEmitter {
666
667
  // /_/ \__,_/\__, /_/_/ /_/\__,_/\__/\___/
667
668
  // /____/
668
669
 
670
+ /**
671
+ * Resets the pagination to page one
672
+ * @fires changePageSize
673
+ */
674
+ resetPagination = (pageSize) => {
675
+ if (this.isDestroyed) {
676
+ throw Error('this.resetPagination is no longer valid. Repository has been destroyed.');
677
+ }
678
+ this.setPage(1);
679
+ }
680
+
669
681
  /**
670
682
  * Sets the pageSize
671
683
  * @fires changePageSize
@@ -779,12 +791,38 @@ export default class Repository extends EventEmitter {
779
791
  * @static
780
792
  */
781
793
  static _calculatePaginationVars = (total, page, pageSize) => {
794
+
795
+ // Special case: empty pages
796
+ if (total < 1) {
797
+ return {
798
+ page,
799
+ pageSize,
800
+ total,
801
+ totalPages: 1,
802
+ pageStart: 0,
803
+ pageEnd: 0,
804
+ pageTotal: 0,
805
+ };
806
+ }
807
+
782
808
  const totalPages = Math.ceil(total / pageSize),
783
- pageStart = !total ? 0 : ((page -1) * pageSize) + 1,
784
- remainder = total > pageSize ? total % pageSize : 0,
785
- pageTotal = (page === 1 && totalPages === 1) ? total :
786
- (page < totalPages ? pageSize : remainder),
787
- pageEnd = !total ? 0 : pageStart -1 + pageTotal;
809
+ pageStart = ((page -1) * pageSize) + 1;
810
+
811
+ let remainder,
812
+ pageEnd,
813
+ pageTotal;
814
+
815
+ if (page === 1 && totalPages === 1) {
816
+ pageTotal = total;
817
+ } else if (page < totalPages) {
818
+ pageTotal = pageSize;
819
+ } else {
820
+ // last page
821
+ remainder = total % pageSize;
822
+ pageTotal = remainder || pageSize;
823
+ }
824
+
825
+ pageEnd = pageStart + pageTotal -1;
788
826
 
789
827
  return {
790
828
  page,
@@ -1302,6 +1340,9 @@ export default class Repository extends EventEmitter {
1302
1340
  if (!_.isArray(entities)) {
1303
1341
  entities = [entities];
1304
1342
  }
1343
+ if (!entities.length) {
1344
+ return;
1345
+ }
1305
1346
  _.each(entities, (entity) => {
1306
1347
  entity.markDeleted(); // Entity is still there, it's just marked for deletion
1307
1348
  });