@onehat/data 1.21.20 → 1.21.21

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.
@@ -1,6 +1,5 @@
1
1
  /** @module Repository */
2
2
 
3
- import Repository from './Repository.js';
4
3
  import AjaxRepository from './Ajax.js';
5
4
  import qs from 'qs';
6
5
  import _ from 'lodash';
@@ -11,9 +10,11 @@ const nonConditionFilters = [
11
10
  'fields',
12
11
  'distinct',
13
12
  'leftJoinWith',
13
+ 'innerJoin',
14
14
  'join',
15
15
  'where',
16
16
  'matching',
17
+ 'groupBy',
17
18
  'contain',
18
19
  'order',
19
20
  'limit',
@@ -30,21 +31,22 @@ class OneBuildRepository extends AjaxRepository {
30
31
  constructor(config = {}) {
31
32
  super(...arguments);
32
33
 
33
- const model = this._getModel();
34
34
  const defaults = {
35
35
 
36
36
  isAutoLoad: false,
37
37
  isAutoSave: false,
38
38
 
39
39
  api: {
40
- get: model + '/get',
41
- add: model + '/add',
42
- edit: model + '/edit',
43
- delete: model + '/delete',
44
- batchAdd: model + '/batchAdd',
45
- batchEdit: model + '/batchEdit',
46
- batchDelete: model + '/batchDelete',
47
- getLastModifiedDate: model + '/getLastModifiedDate',
40
+ get: 'get',
41
+ add: 'add',
42
+ edit: 'edit',
43
+ delete: 'delete',
44
+ batchAdd: 'batchAdd',
45
+ batchEdit: 'batchEdit',
46
+ batchDelete: 'batchDelete',
47
+ reorder: 'reorder',
48
+ duplicate: 'duplicate',
49
+ getLastModifiedDate: 'getLastModifiedDate',
48
50
  },
49
51
 
50
52
  methods: {
@@ -83,7 +85,6 @@ class OneBuildRepository extends AjaxRepository {
83
85
 
84
86
  this.registerEvents([
85
87
  'logout',
86
- 'loadRootNodes',
87
88
  ]);
88
89
 
89
90
  await super.initialize();
@@ -96,7 +97,7 @@ class OneBuildRepository extends AjaxRepository {
96
97
  * Fires off axios request to server
97
98
  * @private
98
99
  */
99
- _send(method, url, data, headers) {
100
+ _send(method, url, data, options = {}) {
100
101
 
101
102
  if (!url) {
102
103
  this.throwError('No url submitted');
@@ -108,12 +109,20 @@ class OneBuildRepository extends AjaxRepository {
108
109
  return;
109
110
  }
110
111
 
112
+ // Create AbortController for this request
113
+ const controller = new AbortController();
114
+ const { signal } = controller;
115
+
116
+ if (options.isLoadRequest && !this.disableLimitToOnlyOneLoadRequest && !this.isUnique && options.requestKey) {
117
+ this._activeLoadRequests.set(options.requestKey, { controller });
118
+ }
119
+
111
120
  const mergedHeaders = _.merge({
112
121
  // 'Content-Type': 'application/json', // Stops axios from using 'application/x-www-form-urlencoded'
113
122
  Accept: 'application/json',
114
- }, this.headers, headers);
123
+ }, this.headers, options.headers);
115
124
 
116
- const options = {
125
+ const axiosOptions = {
117
126
  url,
118
127
  method,
119
128
  baseURL: this.api.baseURL,
@@ -122,16 +131,22 @@ class OneBuildRepository extends AjaxRepository {
122
131
  params: method === 'GET' ? data : null,
123
132
  data: method !== 'GET' ? qs.stringify(data) : null,
124
133
  timeout: this.timeout,
134
+ signal,
125
135
  };
126
136
 
127
137
  if (this.debugMode) {
128
- console.log('Sending ' + url, options);
138
+ console.log('Sending ' + url, axiosOptions);
129
139
  }
130
140
 
131
- this.lastSendOptions = options;
141
+ this.lastSendOptions = axiosOptions;
132
142
 
133
- return this.axios(options)
143
+ return this.axios(axiosOptions)
134
144
  .catch(error => {
145
+ // Don't log or throw error if request was aborted
146
+ if (error.name === 'AbortError' || error.code === 'ERR_CANCELED') {
147
+ return Promise.reject('Request cancelled');
148
+ }
149
+
135
150
  if (this.debugMode) {
136
151
  console.log(url + ' error', error);
137
152
  console.log('response:', error.response);
@@ -146,16 +161,14 @@ class OneBuildRepository extends AjaxRepository {
146
161
 
147
162
  this.throwError(error);
148
163
  return;
164
+ })
165
+ .finally(() => {
166
+ if (options.isLoadRequest && !this.disableLimitToOnlyOneLoadRequest && !this.isUnique && options.requestKey) {
167
+ this._activeLoadRequests.delete(options.requestKey);
168
+ }
149
169
  });
150
170
  }
151
171
 
152
- _getModel() {
153
- if (!this.isUnique) {
154
- return this.name;
155
- }
156
- return this.name.match(/^([^-]*)-(.*)/)[1]; // converts 'ModelName-22f9915c-79f5-4e86-a25b-9446c7b85b63' to 'ModelName'
157
- }
158
-
159
172
  /**
160
173
  * Helper for reloadEntity.
161
174
  * @private
@@ -188,7 +201,7 @@ class OneBuildRepository extends AjaxRepository {
188
201
  }
189
202
  });
190
203
 
191
- if (this.isAutoLoad && this.isLoaded && !this.eventsPaused) {
204
+ if ((this.isAutoLoad || this.isTree) && this.isLoaded && !this.eventsPaused) {
192
205
  if (this.isTree) {
193
206
  return this.loadRootNodes(1);
194
207
  } else {
@@ -304,7 +317,7 @@ class OneBuildRepository extends AjaxRepository {
304
317
  }
305
318
 
306
319
  const data = {
307
- url: this._getModel() + '/reorder',
320
+ url: this.getModel() + '/' + this.api.reorder,
308
321
  data: qs.stringify({
309
322
  ids,
310
323
  dropPosition,
@@ -341,9 +354,9 @@ class OneBuildRepository extends AjaxRepository {
341
354
  this.markLoading();
342
355
 
343
356
  const
344
- Model = this.getSchema().name,
357
+ url = entity.getModel() + '/' + this.api.duplicate,
345
358
  id = entity.id,
346
- result = await this._send('POST', Model + '/duplicate', { id });
359
+ result = await this._send('POST', url, { id });
347
360
 
348
361
  if (!result) {
349
362
  this.markLoading(false);
@@ -360,7 +373,8 @@ class OneBuildRepository extends AjaxRepository {
360
373
 
361
374
  if (!success) {
362
375
  this.markLoading(false);
363
- throw Error(message);
376
+ this.throwError(message);
377
+ return;
364
378
  }
365
379
 
366
380
  // Click duplicateId. The new row appears directly above the one that was duplicated
@@ -390,6 +404,7 @@ class OneBuildRepository extends AjaxRepository {
390
404
  this.total++;
391
405
  this._setPaginationVars();
392
406
  this.emit('changeData', this.entities);
407
+ return entity;
393
408
  }
394
409
 
395
410
  async getSingleEntityFromServer(id) {
@@ -412,13 +427,15 @@ class OneBuildRepository extends AjaxRepository {
412
427
  const params = {};
413
428
  params['conditions[' + idPropertyName + ']'] = id;
414
429
 
415
- const data = _.merge(params, this._baseParams);
430
+ const
431
+ url = this.getModel() + '/' + this.api.get,
432
+ data = _.merge(params, this._baseParams);
416
433
 
417
434
  if (this.debugMode) {
418
435
  console.log('getSingleEntityFromServer', data);
419
436
  }
420
437
 
421
- return this._send(this.methods.get, this.api.get, data)
438
+ return this._send(this.methods.get, url, data)
422
439
  .then(result => {
423
440
  if (this.debugMode) {
424
441
  console.log('Response for getSingleEntityFromServer for ' + this.name, result);
@@ -468,7 +485,9 @@ class OneBuildRepository extends AjaxRepository {
468
485
  console.log('getLastModifiedDate');
469
486
  }
470
487
 
471
- return this._send(this.methods.get, this.api.getLastModifiedDate, this._baseParams)
488
+ const url = this.getModel() + '/' + this.api.getLastModifiedDate;
489
+
490
+ return this._send(this.methods.get, url, this._baseParams)
472
491
  .then(result => {
473
492
  if (this.debugMode) {
474
493
  console.log('Response for getLastModifiedDate for ' + this.name, result);
@@ -525,20 +544,30 @@ class OneBuildRepository extends AjaxRepository {
525
544
  }
526
545
 
527
546
  return this.axios(data)
528
- .then((result) => {
529
- if (this.debugMode) {
530
- console.log('login response', result);
531
- }
547
+ .catch((error) => {
532
548
 
533
- const response = result.data;
534
- if (!response.success) {
535
- this.throwError(response.data); // TODO: Fix back-end, so OneBuild submits the error message on response.message, not response.data
536
- return false;
537
- }
549
+ if (this.debugMode) {
550
+ console.log(data.url + ' error', error);
551
+ console.log('response:', error.response);
552
+ }
553
+
554
+ this.throwError(error);
555
+ return;
556
+ })
557
+ .then((result) => {
558
+ if (this.debugMode) {
559
+ console.log('login response', result);
560
+ }
538
561
 
539
- const userData = response.data;
540
- return userData;
541
- });
562
+ const response = result.data;
563
+ if (!response.success) {
564
+ this.throwError(response.data); // TODO: Fix back-end, so OneBuild submits the error message on response.message, not response.data
565
+ return false;
566
+ }
567
+
568
+ const userData = response.data;
569
+ return userData;
570
+ });
542
571
  }
543
572
 
544
573
  /**
@@ -618,396 +647,6 @@ class OneBuildRepository extends AjaxRepository {
618
647
  });
619
648
  }
620
649
 
621
-
622
- // ______
623
- // /_ __/_______ ___ _____
624
- // / / / ___/ _ \/ _ \/ ___/
625
- // / / / / / __/ __(__ )
626
- // /_/ /_/ \___/\___/____/
627
-
628
- /**
629
- * Loads the root nodes of this tree.
630
- */
631
- loadRootNodes(depth) {
632
- this.ensureTree();
633
- if (this.isDestroyed) {
634
- this.throwError('this.setRootNode is no longer valid. Repository has been destroyed.');
635
- return;
636
- }
637
- if (!this.isOnline) {
638
- this.throwError('Offline');
639
- return;
640
- }
641
-
642
- this.emit('beforeLoad'); // TODO: canceling beforeLoad will cancel the load operation
643
- this.markLoading();
644
-
645
- const data = _.merge({ depth }, this._baseParams, this._params);
646
-
647
- if (this.debugMode) {
648
- console.log('loadRootNodes', data);
649
- }
650
-
651
- return this._send('POST', this._getModel() + '/getNodes', data)
652
- .then((result) => {
653
- if (this.debugMode) {
654
- console.log('Response for loadRootNodes', result);
655
- }
656
-
657
- if (this.isDestroyed) {
658
- // If this repository gets destroyed before it has a chance
659
- // to process the Ajax request, just ignore the response.
660
- return;
661
- }
662
-
663
- const {
664
- root,
665
- success,
666
- total,
667
- message
668
- } = this._processServerResponse(result);
669
-
670
- if (!success) {
671
- this.throwError(message);
672
- return;
673
- }
674
-
675
- this._destroyEntities();
676
-
677
- // Set the current entities
678
- const oThis = this;
679
- this.entities = _.map(root, (data) => {
680
- const entity = Repository._createEntity(oThis.schema, data, this, true);
681
- oThis._relayEntityEvents(entity);
682
- return entity;
683
- });
684
-
685
- this.assembleTreeNodes();
686
-
687
- // Set the total records that pass filter
688
- this.total = total;
689
- this._setPaginationVars();
690
-
691
- this.areRootNodesLoaded = true;
692
-
693
-
694
- // Don't emit events for root nodes...
695
- this.rehash();
696
- this.emit('loadRootNodes', this);
697
- // this.emit('changeData', this.entities);
698
-
699
- return this.getBy((entity) => {
700
- return entity.isRoot;
701
- });
702
- })
703
- .finally(() => {
704
- this.markLoading(false);
705
- });
706
- }
707
-
708
- /**
709
- * Loads (or reloads) the supplied treeNode
710
- */
711
- loadNode(treeNode, depth = 1) {
712
- this.ensureTree();
713
- if (this.isDestroyed) {
714
- this.throwError('this.loadNode is no longer valid. Repository has been destroyed.');
715
- return;
716
- }
717
- if (!this.isOnline) {
718
- this.throwError('Offline');
719
- return;
720
- }
721
-
722
- // If children already exist, remove them from the repository
723
- // This way, we can reload just a portion of the tree
724
- if (!_.isEmpty(treeNode.children)) {
725
- const children = treeNode.children;
726
- treeNode.children = [];
727
-
728
- const oThis = this;
729
- _.each(children, (child) => {
730
- oThis.removeEntity(child);
731
- });
732
- }
733
-
734
- this.markLoading();
735
-
736
- const data = _.merge({ depth, nodeId: treeNode.id, }, this._baseParams, this._params);
737
-
738
- if (this.debugMode) {
739
- console.log('loadNode', data);
740
- }
741
-
742
- return this._send('POST', this._getModel() + '/getNodes', data)
743
- .then((result) => {
744
- if (this.debugMode) {
745
- console.log('Response for loadNode', result);
746
- }
747
-
748
- if (this.isDestroyed) {
749
- // If this repository gets destroyed before it has a chance
750
- // to process the Ajax request, just ignore the response.
751
- return;
752
- }
753
-
754
- const {
755
- root,
756
- success,
757
- total,
758
- message
759
- } = this._processServerResponse(result);
760
-
761
- if (!success) {
762
- this.throwError(message);
763
- return;
764
- }
765
-
766
- // Set the current entities
767
- const oThis = this;
768
- const children = _.map(root, (data) => {
769
- const entity = Repository._createEntity(oThis.schema, data, this, true);
770
- oThis._relayEntityEvents(entity);
771
- return entity;
772
- });
773
-
774
- this.entities = this.entities.concat(children);
775
-
776
- this.assembleTreeNodes();
777
-
778
- this._setPaginationVars();
779
-
780
- this.rehash();
781
- // this.emit('changeData', this.entities);
782
- this.emit('load', this);
783
-
784
- return children;
785
- })
786
- .finally(() => {
787
- this.markLoading(false);
788
- });
789
- }
790
-
791
- /**
792
- * Loads (or reloads) the children of the supplied treeNode
793
- */
794
- loadChildNodes(treeNode, depth = 1) {
795
- this.ensureTree();
796
- if (this.isDestroyed) {
797
- this.throwError('this.loadChildNodes is no longer valid. Repository has been destroyed.');
798
- return;
799
- }
800
- if (!this.isOnline) {
801
- this.throwError('Offline');
802
- return;
803
- }
804
-
805
- // If children already exist, remove them from the repository
806
- // This way, we can reload just a portion of the tree
807
- if (!_.isEmpty(treeNode.children)) {
808
- _.each(treeNode.children, (child) => {
809
- treeNode.repository.removeTreeNode(child);
810
- });
811
- treeNode.children = [];
812
- }
813
-
814
- this.markLoading();
815
-
816
- const data = _.merge({ depth, parentId: treeNode.id, }, this._baseParams, this._params);
817
-
818
- if (this.debugMode) {
819
- console.log('loadChildNodes', data);
820
- }
821
-
822
- return this._send('POST', this._getModel() + '/getNodes', data)
823
- .then((result) => {
824
- if (this.debugMode) {
825
- console.log('Response for loadChildNodes', result);
826
- }
827
-
828
- if (this.isDestroyed) {
829
- // If this repository gets destroyed before it has a chance
830
- // to process the Ajax request, just ignore the response.
831
- return;
832
- }
833
-
834
- const {
835
- root,
836
- success,
837
- total,
838
- message
839
- } = this._processServerResponse(result);
840
-
841
- if (!success) {
842
- this.throwError(message);
843
- return;
844
- }
845
-
846
- // Set the current entities
847
- const oThis = this;
848
- const children = _.map(root, (data) => {
849
- const entity = Repository._createEntity(oThis.schema, data, this, true);
850
- oThis._relayEntityEvents(entity);
851
- return entity;
852
- });
853
-
854
- this.entities = this.entities.concat(children);
855
-
856
- this.assembleTreeNodes();
857
-
858
- this._setPaginationVars();
859
-
860
- this.rehash();
861
- // this.emit('changeData', this.entities);
862
- this.emit('load', this);
863
-
864
- return children;
865
- })
866
- .finally(() => {
867
- this.markLoading(false);
868
- });
869
- }
870
-
871
- /**
872
- * Override the AjaxRepository to we can reload a treeNode if needed
873
- */
874
- reloadEntity(entity, callback = null) {
875
- if (!entity.isTree) {
876
- return super.reloadEntity(entity, callback);
877
- }
878
-
879
- return this.loadNode(entity, 1);
880
- }
881
-
882
- /**
883
- * Searches all nodes for the supplied text.
884
- * This basically takes the search query and returns whatever the server sends
885
- */
886
- searchNodes(q) {
887
- this.ensureTree();
888
- if (this.isDestroyed) {
889
- this.throwError('this.searchNodes is no longer valid. Repository has been destroyed.');
890
- return;
891
- }
892
- if (!this.isOnline) {
893
- this.throwError('Offline');
894
- return;
895
- }
896
-
897
- const data = _.merge({ q, }, this._baseParams, this._params);
898
-
899
- if (this.debugMode) {
900
- console.log('searchNodes', data);
901
- }
902
-
903
- return this._send('POST', this._getModel() + '/searchNodes', data)
904
- .then((result) => {
905
- if (this.debugMode) {
906
- console.log('Response for searchNodes', result);
907
- }
908
-
909
- if (this.isDestroyed) {
910
- // If this repository gets destroyed before it has a chance
911
- // to process the Ajax request, just ignore the response.
912
- return;
913
- }
914
-
915
- const {
916
- root,
917
- success,
918
- total,
919
- message
920
- } = this._processServerResponse(result);
921
-
922
- if (!success) {
923
- this.throwError(message);
924
- return;
925
- }
926
-
927
- return root;
928
- })
929
- .finally(() => {
930
- this.markLoading(false);
931
- });
932
- }
933
-
934
- /**
935
- * Alias for loadChildren
936
- */
937
- reloadChildren(treeNode, depth) {
938
- return this.loadChildren(treeNode, depth);
939
- }
940
-
941
- /**
942
- * Moves the supplied treeNode to a new position on the tree
943
- * @returns id of common ancestor node
944
- */
945
- moveTreeNode(treeNode, newParentId) {
946
- this.ensureTree();
947
- if (this.isDestroyed) {
948
- this.throwError('this.moveTreeNode is no longer valid. Repository has been destroyed.');
949
- return;
950
- }
951
- if (!this.isOnline) {
952
- this.throwError('Offline');
953
- return;
954
- }
955
-
956
- const oldParentId = treeNode.parent?.id;
957
-
958
- const data = _.merge({ nodeId: treeNode.id, parentId: newParentId, }, this._baseParams, this._params);
959
-
960
- if (this.debugMode) {
961
- console.log('moveTreeNode', data);
962
- }
963
-
964
- return this._send('POST', this._getModel() + '/moveNode', data)
965
- .then((result) => {
966
- if (this.debugMode) {
967
- console.log('Response for searchNodes', result);
968
- }
969
-
970
- if (this.isDestroyed) {
971
- // If this repository gets destroyed before it has a chance
972
- // to process the Ajax request, just ignore the response.
973
- return;
974
- }
975
-
976
- const {
977
- root: {
978
- commonAncestorId,
979
- oldParent,
980
- newParent,
981
- node,
982
- },
983
- success,
984
- total,
985
- message
986
- } = this._processServerResponse(result);
987
-
988
- if (!success) {
989
- this.throwError(message);
990
- return;
991
- }
992
-
993
- // move it from oldParent.children to newParent.children
994
- const
995
- oldParentRecord = this.getById(oldParentId),
996
- newParentRecord = this.getById(newParentId);
997
-
998
- oldParentRecord?.loadOriginalData(oldParent);
999
- newParentRecord.loadOriginalData(newParent);
1000
- treeNode.loadOriginalData(node);
1001
-
1002
- this.assembleTreeNodes();
1003
-
1004
- return commonAncestorId;
1005
- })
1006
- .finally(() => {
1007
- this.markLoading(false);
1008
- });
1009
- }
1010
-
1011
650
  }
1012
651
 
1013
652