cronapp-common-js 2.8.4 → 2.8.8

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.
@@ -2,6 +2,7 @@
2
2
  var ISO_PATTERN = new RegExp("(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d\\.\\d+([+-][0-2]\\d:[0-5]\\d|Z))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z))|(\\d{4}-[01]\\d-[0-3]\\dT[0-2]\\d:[0-5]\\d([+-][0-2]\\d:[0-5]\\d|Z))");
3
3
  var TIME_PATTERN = new RegExp("PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)(?:\\.(\\d+)?)?S)?");
4
4
  var DEP_PATTERN = new RegExp("\\{\\{(.*?)\\|raw\\}\\}");
5
+ var HTTP_STATUS = new RegExp("HTTP\\/1\\.1 (\\d+) (.*)");
5
6
 
6
7
 
7
8
  (function ($) {
@@ -78,6 +79,7 @@ var initDatasource = function(scope, element, attrs, DatasetManager, $timeout, $
78
79
  onAfterUpdate: attrs.onAfterUpdate,
79
80
  onBeforeDelete: attrs.onBeforeDelete,
80
81
  onAfterDelete: attrs.onAfterDelete,
82
+ onChangeStatus: attrs.onChangeStatus,
81
83
  onGet: attrs.onGet,
82
84
  onPost: attrs.onPost,
83
85
  onPut: attrs.onPut,
@@ -341,6 +343,23 @@ angular.module('datasourcejs', [])
341
343
  // Global dataset List
342
344
  this.datasets = {};
343
345
 
346
+ const $httpLegacy = (config) => {
347
+ let http = $http(config);
348
+ return {
349
+ success: function (thenCallback) {
350
+ http.then(response => {
351
+ thenCallback(response.data, response.status, response.headers, response.config);
352
+ });
353
+ return this;
354
+ },
355
+ error: function (catchCallback) {
356
+ http.catch(response => {
357
+ catchCallback(response.data, response.status, response.headers, response.config);
358
+ });
359
+ return this;
360
+ }
361
+ }
362
+ };
344
363
  /**
345
364
  * Class representing a single dataset
346
365
  */
@@ -451,8 +470,8 @@ angular.module('datasourcejs', [])
451
470
  update: function(url, object) {
452
471
  return this.call(url, "PUT", object, false);
453
472
  },
454
- remove: function(url) {
455
- return this.call(url, "DELETE", null, true);
473
+ remove: function(url, object) {
474
+ return this.call(url, "DELETE", object, true);
456
475
  },
457
476
  call: function(url, verb, obj, applyScope) {
458
477
  var object = {};
@@ -499,6 +518,7 @@ angular.module('datasourcejs', [])
499
518
  delete cloneObject.$$hashKey;
500
519
  delete cloneObject.__fromMemory;
501
520
  delete cloneObject.__odatafiles;
521
+ delete cloneObject.__$masterExpression;
502
522
 
503
523
  for (var key in cloneObject) {
504
524
  if (key.indexOf('__odataFile_') > -1) {
@@ -507,28 +527,30 @@ angular.module('datasourcejs', [])
507
527
  }
508
528
  }
509
529
 
510
- // Get an ajax promise
511
- this.$promise = _self.getService(verb)({
512
- method: verb,
513
- url: _self.removeSlash(((window.hostApp || "") + url)),
514
- data: (object) ? JSON.stringify(cloneObject) : null,
515
- headers: _self.headers,
516
- rawData: (object) ? cloneObject : null
517
- }).success(function(data, status, headers, config) {
530
+ for (var key in cloneObject) {
531
+ if (cloneObject.hasOwnProperty(key)) {
532
+ let value = cloneObject[key];
533
+ if (_self.isAutoGeneratedValue(value)) {
534
+ delete cloneObject[key];
535
+ }
536
+ }
537
+ }
538
+
539
+ var success = function(data, status, headers, config, batchPostponed) {
518
540
  _self.busy = false;
519
541
  if (_callback) {
520
542
  if (_self.isOData()) {
521
543
  if (data.d != null && data.d.result != null) {
522
544
  _self.normalizeData(data.d.result);
523
- _callback(data.d.result, true);
545
+ _callback(data.d.result, true, batchPostponed);
524
546
  } else if (data.d != null) {
525
547
  _self.normalizeObject(data.d);
526
- _callback(data.d, true);
548
+ _callback(data.d, true, batchPostponed);
527
549
  } else {
528
- _callback(data, true);
550
+ _callback(data, true, batchPostponed);
529
551
  }
530
552
  } else {
531
- _callback(isCronapiQuery?data.value:data, true);
553
+ _callback(isCronapiQuery?data.value:data, true, batchPostponed);
532
554
  }
533
555
  }
534
556
  if (isCronapiQuery || _self.isOData()) {
@@ -540,26 +562,49 @@ angular.module('datasourcejs', [])
540
562
  }
541
563
  _self.$scope.cronapi.evalInContext(JSON.stringify(commands));
542
564
  }
543
- }).error(function(data, status, headers, config) {
544
- _self.busy = false;
545
- var msg;
546
- if (_self.isOData()) {
547
- msg = data.error.message.value;
548
- } else {
549
- msg = isCronapiQuery&&data.value?data.value:data
550
- }
551
- _self.handleError(msg);
552
- if (_callbackError) {
553
- _callbackError(msg);
554
- }
555
- });
565
+ };
566
+
567
+ var ds = _self.getParentDatasource();
568
+ let batchObj = ds.getBatchDataItem(object);
569
+ if (batchObj && batchObj.result) {
570
+ let idx = ds.batchServiceData.indexOf(batchObj);
571
+ ds.batchServiceData.splice(idx, 1);
572
+ $timeout(() => {
573
+ success(batchObj.result);
574
+ },0);
556
575
 
557
- this.$promise.then = function(callback) {
576
+ this.$promise = {};
577
+ } else {
578
+ // Get an ajax promise
579
+ this.$promise = _self.getService(verb, object)({
580
+ method: verb,
581
+ url: _self.removeSlash(((window.hostApp || "") + url)),
582
+ data: verb!='DELETE'?((object) ? JSON.stringify(cloneObject) : null):null,
583
+ headers: _self.headers,
584
+ rawData: (object) ? cloneObject : null,
585
+ originalObject: (object) ? object : null,
586
+ urlPart: url
587
+ }).success(success).error(function (data, status, headers, config) {
588
+ _self.busy = false;
589
+ var msg;
590
+ if (_self.isOData()) {
591
+ msg = data.error.message.value;
592
+ } else {
593
+ msg = isCronapiQuery && data.value ? data.value : data
594
+ }
595
+ _self.handleError(msg);
596
+ if (_callbackError) {
597
+ _callbackError(msg);
598
+ }
599
+ });
600
+ }
601
+
602
+ this.$promise.then = function (callback) {
558
603
  _callback = callback;
559
604
  return this;
560
605
  }
561
606
 
562
- this.$promise.error = function(callback) {
607
+ this.$promise.error = function (callback) {
563
608
  _callbackError = callback;
564
609
  return this;
565
610
  }
@@ -567,6 +612,12 @@ angular.module('datasourcejs', [])
567
612
  }
568
613
  }
569
614
 
615
+ this.isAutoGeneratedValue = function(value) {
616
+ return typeof value === 'string'
617
+ && value.length > 10
618
+ && (value.startsWith("$autogenerated$") || value.substring(1).startsWith("$autogenerated$"));
619
+ }
620
+
570
621
  this.getIndexedDB = function(properties) {
571
622
  if (!window.indexedDB) {
572
623
  window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
@@ -666,6 +717,212 @@ angular.module('datasourcejs', [])
666
717
 
667
718
  }
668
719
 
720
+ this.batchServiceData = [];
721
+
722
+ this.getBatchService = function(verb) {
723
+ return function(properties) {
724
+ var promise = {
725
+ verb: verb,
726
+ properties: properties,
727
+ successCallback: null,
728
+ errorCallback: null,
729
+ success: function (successCallback) {
730
+ this.successCallback = successCallback;
731
+ return this;
732
+ },
733
+
734
+ error: function (errorCallback) {
735
+ this.errorCallback = errorCallback;
736
+ return this;
737
+ }
738
+ };
739
+
740
+ $timeout(function() {
741
+ var ds = this.getParentDatasource();
742
+ let obj = properties.originalObject || properties.rawData || properties.data || this.active
743
+
744
+ let entity = this.entity;
745
+
746
+ if (verb == 'PUT') {
747
+ entity = this.getEditionURL(obj);
748
+ }
749
+
750
+ if (verb == 'DELETE') {
751
+ entity = this.getDeletionURL(obj);
752
+ }
753
+
754
+ if (entity.indexOf("/") > 0) {
755
+ entity = entity.substring(entity.lastIndexOf("/")+1, entity.length);
756
+ }
757
+
758
+ ds.batchServiceData.push({
759
+ entity: entity,
760
+ data: obj,
761
+ promise: promise
762
+ });
763
+
764
+ if (promise.successCallback) {
765
+ promise.successCallback.call(this, obj, null, null, null, true);
766
+ }
767
+ }.bind(this));
768
+
769
+ return promise;
770
+ }.bind(this);
771
+ }
772
+
773
+ this.batchEnabled = function(obj) {
774
+ if (obj && this.hasPendingChanges()) {
775
+ return this.getBatchDataItem(obj) != null ? false : true;
776
+ }
777
+
778
+ return false;
779
+ }
780
+
781
+ this.getBatchDataItem = function(obj) {
782
+ if (obj) {
783
+ var ds = this.getParentDatasource();
784
+ for (let i = 0; i < ds.batchServiceData.length; i++) {
785
+ let data = ds.batchServiceData[i].data;
786
+ if (data.__$id == obj.__$id) {
787
+ return ds.batchServiceData[i];
788
+ }
789
+ }
790
+ }
791
+
792
+ return null;
793
+ }
794
+
795
+ this.performBatchPost = function(originCallback) {
796
+ return new Promise((resolve, reject) => {
797
+ let boundary = "batch_" + this.uuidv4();
798
+ let odataPost = "";
799
+
800
+ odataPost += "--" + boundary + "\n";
801
+ let changeSet = "changeset_" + this.uuidv4();
802
+ odataPost += "Content-Type: multipart/mixed; boundary=" + changeSet + "\n";
803
+
804
+ for (let i = 0; i < this.batchServiceData.length; i++) {
805
+ let batchData = this.batchServiceData[i];
806
+
807
+ odataPost += "--" + changeSet + "\n";
808
+
809
+ odataPost += "Content-Type: application/http\n";
810
+ odataPost += "Content-Transfer-Encoding:binary\n";
811
+
812
+ odataPost += batchData.promise.properties.method + " " + batchData.entity + " HTTP/1.1\n";
813
+ odataPost += "Content-Type: application/json\n";
814
+ odataPost += "Accept: application/json\n";
815
+ odataPost += "X-Master-Id: "+batchData.promise.properties.originalObject.__$id+"\n";
816
+ if (batchData.promise.properties.originalObject.__$masterExpression) {
817
+ odataPost += "X-Detail-Fill: " + batchData.promise.properties.originalObject.__$masterExpression + "\n";
818
+ }
819
+
820
+ let headers = batchData.promise.properties.headers;
821
+ for (var key in headers) {
822
+ if (headers.hasOwnProperty(key)) {
823
+ odataPost += key + ": " + headers[key] + "\n";
824
+ }
825
+ }
826
+
827
+ if (batchData.promise.properties.method != 'DELETE') {
828
+ odataPost += batchData.promise.properties.data + "\n";
829
+ }
830
+
831
+ }
832
+
833
+ odataPost += "--" + changeSet + "--\n";
834
+ odataPost += "--" + boundary + "--\n";
835
+ console.log(odataPost);
836
+
837
+ let url = this.entity;
838
+ if (url.indexOf("/") > 0) {
839
+ url = url.substring(0, url.lastIndexOf("/"));
840
+ }
841
+
842
+ let headers = {};
843
+
844
+ this.copy(this.headers, headers);
845
+ headers["Content-Type"] = "multipart/mixed; boundary=" + boundary;
846
+
847
+ let error = (data, status, headers, config) => {
848
+ let callback;
849
+ if (this.batchServiceData.length > 0) {
850
+ callback = this.batchServiceData[0].promise.errorCallback;
851
+ }
852
+
853
+ if (callback) {
854
+ callback(data, status, headers, config, false);
855
+ } else {
856
+ this.handleError(data)
857
+ }
858
+
859
+ this.batchServiceData = [];
860
+ };
861
+
862
+ $httpLegacy({
863
+ method: "POST",
864
+ url: _self.removeSlash(((window.hostApp || "") + url + "/$batch")),
865
+ data: odataPost,
866
+ headers: headers,
867
+ }).success(function (data, status, headers, config, batchPostponed) {
868
+ let result = this.parseBatchResult(data);
869
+ for (let i = 0; i < result.length; i++) {
870
+ if (result[i].status >= 400) {
871
+ error(result[i].data, result[i].status);
872
+ return;
873
+ }
874
+ }
875
+ for (let i = 0; i < this.batchServiceData.length; i++) {
876
+ this.batchServiceData[i].result = result[i].data == null ? this.batchServiceData[i].data : result[i].data;
877
+ }
878
+
879
+ if (originCallback) {
880
+ originCallback();
881
+ } else {
882
+ let callback;
883
+ if (this.batchServiceData.length > 0) {
884
+ callback = this.batchServiceData[0].promise.successCallback;
885
+ }
886
+
887
+ if (callback) {
888
+ this.batchServiceData.splice(0, 1);
889
+ callback(result[0].data, result[0].status, headers, config, false);
890
+ }
891
+ }
892
+
893
+ }.bind(this)).error(error);
894
+ });
895
+ }
896
+
897
+ this.parseBatchResult = function(data) {
898
+ let results = [];
899
+ let lines = data.split("\n");
900
+ let status;
901
+ for (let j=0;j<lines.length;j++) {
902
+ let line = lines[j];
903
+ if (line.startsWith("{")) {
904
+ results.push({
905
+ status: status,
906
+ data: JSON.parse(line)
907
+ });
908
+ }
909
+
910
+ if (line.startsWith("HTTP/1.1")) {
911
+ var g = HTTP_STATUS.exec(line);
912
+ status = g[1];
913
+ }
914
+
915
+ if (line.startsWith("HTTP/1.1") && line.indexOf("No Content") > 0) {
916
+ results.push({
917
+ status: status,
918
+ data: null
919
+ });
920
+ }
921
+ }
922
+
923
+ return results;
924
+ }
925
+
669
926
  this.uuidv4 = function() {
670
927
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
671
928
  var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
@@ -673,7 +930,7 @@ angular.module('datasourcejs', [])
673
930
  });
674
931
  }
675
932
 
676
- this.getService = function(verb) {
933
+ this.getService = function(verb, object) {
677
934
  _self = this;
678
935
  var event = eval("this.on"+verb);
679
936
 
@@ -790,7 +1047,10 @@ angular.module('datasourcejs', [])
790
1047
 
791
1048
  }
792
1049
 
793
- return $http;
1050
+ if (this.batchEnabled(object) && verb != 'GET') {
1051
+ return this.getBatchService(verb);
1052
+ }
1053
+ return $httpLegacy;
794
1054
  }
795
1055
 
796
1056
  /**
@@ -1096,6 +1356,14 @@ angular.module('datasourcejs', [])
1096
1356
  }
1097
1357
  }
1098
1358
 
1359
+ this.getParentDatasource = function() {
1360
+ if (this.dependentLazyPost) {
1361
+ return eval(this.dependentLazyPost).getParentDatasource();
1362
+ }
1363
+
1364
+ return this
1365
+ }
1366
+
1099
1367
  this.updateObjectAtIndex = function(obj, data, idx) {
1100
1368
  data = data || this.data;
1101
1369
 
@@ -1105,6 +1373,7 @@ angular.module('datasourcejs', [])
1105
1373
  delete data[idx].__original;
1106
1374
  delete data[idx].__originalIdx;
1107
1375
  delete data[idx].__odatafiles;
1376
+ delete data[idx].__$masterExpression;
1108
1377
  }
1109
1378
 
1110
1379
  this.cleanDependentBuffer = function() {
@@ -1169,23 +1438,25 @@ angular.module('datasourcejs', [])
1169
1438
  }
1170
1439
 
1171
1440
  this.cleanDependentBuffer();
1441
+ this.batchServiceData = [];
1172
1442
  if (callback) {
1173
1443
  callback();
1174
1444
  }
1175
1445
  }
1176
1446
 
1177
- this.flushDependencies = function(callback) {
1447
+ this.flushDependencies = function(callback, batchPostponed) {
1448
+ var reset = [];
1178
1449
  if (this.dependentData) {
1179
1450
 
1180
1451
  var ins = function() {
1181
1452
 
1182
1453
  reduce(this.dependentData, function (item, resolve) {
1183
- item.storeDependentBuffer(function () {
1454
+ reset.push(item.storeDependentBuffer(function () {
1184
1455
  resolve();
1185
- });
1456
+ }, undefined, batchPostponed))
1186
1457
  }.bind(this), function () {
1187
1458
  if (callback) {
1188
- callback();
1459
+ callback(reset);
1189
1460
  }
1190
1461
  }.bind(this))
1191
1462
 
@@ -1194,7 +1465,7 @@ angular.module('datasourcejs', [])
1194
1465
  reduce(reverseArr(this.dependentData), function (item, resolve) {
1195
1466
  item.storeDependentBuffer(function () {
1196
1467
  resolve();
1197
- }, true);
1468
+ }, true, batchPostponed);
1198
1469
  }.bind(this), function () {
1199
1470
  ins();
1200
1471
  }.bind(this))
@@ -1202,37 +1473,56 @@ angular.module('datasourcejs', [])
1202
1473
 
1203
1474
  } else {
1204
1475
  if (callback) {
1205
- callback();
1476
+ callback(reset);
1206
1477
  }
1207
1478
  }
1208
1479
  }
1209
1480
 
1210
- this.postBatchData = function(callback) {
1481
+ this.postBatchData = function(callbackClient, dontPostpone) {
1482
+ let batchPostponed = dontPostpone?false:true;
1483
+ if (!dontPostpone) {
1484
+ this.batchServiceData = [];
1485
+ }
1486
+ let callback = ()=> {
1487
+ if (batchPostponed) {
1488
+ batchPostponed = false;
1489
+ this.performBatchPost(function() {
1490
+ this.postBatchData(callbackClient, true);
1491
+ }.bind(this));
1492
+ } else {
1493
+ if (callbackClient) {
1494
+ callbackClient();
1495
+ }
1496
+ }
1497
+ };
1211
1498
  this.postingBatch = true;
1212
1499
  var cleanFuncs = [];
1213
1500
  var func = function() {
1214
- cleanFuncs.push(this.storeDependentBuffer(function () {
1215
- reduce(this.dependentData, function (item, resolve) {
1216
- cleanFuncs.push(item.storeDependentBuffer(function () {
1217
- resolve();
1218
- }));
1219
- }.bind(this), function () {
1220
- this.postingBatch = false;
1221
- for (var x=0;x<cleanFuncs.length;x++) {
1222
- cleanFuncs[x]();
1223
- }
1224
- if (callback) {
1225
- callback();
1226
- }
1227
- }.bind(this))
1228
- }.bind(this)));
1501
+ this.storeDependentBuffer(function () {
1502
+ cleanFuncs.push(this.storeDependentBuffer(function () {
1503
+ reduce(this.dependentData, function (item, resolve) {
1504
+ cleanFuncs.push(item.storeDependentBuffer(function () {
1505
+ resolve();
1506
+ }, false, batchPostponed));
1507
+ }.bind(this), function () {
1508
+ this.postingBatch = false;
1509
+ for (var x=0;x<cleanFuncs.length;x++) {
1510
+ cleanFuncs[x]();
1511
+ }
1512
+ if (callback) {
1513
+ callback();
1514
+ }
1515
+ }.bind(this))
1516
+
1517
+ }.bind(this), false, batchPostponed));
1518
+ }.bind(this), true, batchPostponed);
1229
1519
  }.bind(this);
1230
1520
 
1231
- //Primeiro executa as remoções
1521
+ //Primeiro executa as remoções dos filhos
1232
1522
  reduce(reverseArr(this.dependentData), function (item, resolve) {
1233
1523
  item.storeDependentBuffer(function () {
1234
1524
  resolve();
1235
- }, true);
1525
+ }, true, batchPostponed);
1236
1526
  }.bind(this), function() {
1237
1527
  func();
1238
1528
  }.bind(this));
@@ -1257,7 +1547,7 @@ angular.module('datasourcejs', [])
1257
1547
  }
1258
1548
  }
1259
1549
 
1260
- this.storeDependentBuffer = function(callback, onlyRemove) {
1550
+ this.storeDependentBuffer = function(callback, onlyRemove, batchMode) {
1261
1551
  var _self = this;
1262
1552
  var dependentDS = eval(_self.dependentLazyPost);
1263
1553
 
@@ -1311,18 +1601,28 @@ angular.module('datasourcejs', [])
1311
1601
  }
1312
1602
 
1313
1603
  if (_self.parameters) {
1314
- var params = _self.getParametersMap(item.__parentId?item.__parentId:null);
1604
+ var params = _self.getParametersMap(item.__parentId ? item.__parentId : null);
1315
1605
  for (var key in params) {
1316
1606
  if (params.hasOwnProperty(key)) {
1317
1607
  updateObjectValue(item, key, params[key]);
1318
1608
  }
1319
1609
  }
1610
+
1611
+ let masterExpression = _self.getParametersBatchExpression(item.__parentId ? item.__parentId : null);
1612
+ item.__$masterExpression = masterExpression;
1320
1613
  }
1321
1614
 
1322
1615
  if (item.__status == "inserted") {
1323
1616
  (function (oldObj) {
1324
- var odataFiles = _self.processODataFiles(oldObj);
1325
- _self.insert(oldObj, function (newObj) {
1617
+ var odataFiles;
1618
+ if (!batchMode) {
1619
+ odataFiles = _self.processODataFiles(oldObj);
1620
+ }
1621
+ _self.insert(oldObj, function (newObj, hotData, batchPostponed) {
1622
+ if (batchPostponed) {
1623
+ resolve();
1624
+ return;
1625
+ }
1326
1626
  var sender = oldObj.__sender;
1327
1627
  var idx = _self.getIndexOfListTempBuffer(oldObj, array);
1328
1628
  var isFromMemory = false;
@@ -1343,7 +1643,7 @@ angular.module('datasourcejs', [])
1343
1643
 
1344
1644
  if (odataFiles && odataFiles.length > 0) {
1345
1645
  _self.sendODataFiles(odataFiles, newObj, function (result) {
1346
- this.copy(result.data, currentObj);
1646
+ _self.copy(result.data, currentObj);
1347
1647
  }.bind(this), function() {
1348
1648
  resolve();
1349
1649
  });
@@ -1358,8 +1658,15 @@ angular.module('datasourcejs', [])
1358
1658
 
1359
1659
  else if (item.__status == "updated") {
1360
1660
  (function (oldObj) {
1361
- var odataFiles = _self.processODataFiles(oldObj);
1362
- _self.update(oldObj, function (newObj) {
1661
+ var odataFiles;
1662
+ if (!batchMode) {
1663
+ odataFiles = _self.processODataFiles(oldObj);
1664
+ }
1665
+ _self.update(oldObj, function (newObj, hotData, batchPostponed) {
1666
+ if (batchPostponed) {
1667
+ resolve();
1668
+ return;
1669
+ }
1363
1670
  var sender = oldObj.__sender;
1364
1671
  var idx = _self.getIndexOfListTempBuffer(oldObj, array);
1365
1672
  var isFromMemory = false;
@@ -1379,7 +1686,7 @@ angular.module('datasourcejs', [])
1379
1686
  }
1380
1687
  if (odataFiles && odataFiles.length > 0) {
1381
1688
  _self.sendODataFiles(odataFiles, newObj, function (result) {
1382
- this.copy(result.data, currentObj);
1689
+ _self.copy(result.data, currentObj);
1383
1690
  }.bind(this), function() {
1384
1691
  resolve();
1385
1692
  });
@@ -1392,9 +1699,13 @@ angular.module('datasourcejs', [])
1392
1699
  })(item);
1393
1700
  }
1394
1701
 
1395
- else if (item.__status == "deleted") {
1702
+ else if (item.__status == "deleted" && onlyRemove) {
1396
1703
  (function (oldObj) {
1397
- _self.remove(oldObj, function () {
1704
+ _self.remove(oldObj, function (newObj, hotData, batchPostponed) {
1705
+ if (batchPostponed) {
1706
+ resolve();
1707
+ return;
1708
+ }
1398
1709
  if (_self.events.delete) {
1399
1710
  var param = {};
1400
1711
  _self.copy(oldObj, param);
@@ -1425,8 +1736,10 @@ angular.module('datasourcejs', [])
1425
1736
  this.inserting = false;
1426
1737
  this.hasMemoryData = false;
1427
1738
  this.memoryData = null;
1428
- this.notifyPendingChanges(this.hasMemoryData);
1429
- if (this.events.afterchanges) {
1739
+ if (!batchMode) {
1740
+ this.notifyPendingChanges(this.hasMemoryData);
1741
+ }
1742
+ if (this.events.afterchanges && !batchMode) {
1430
1743
  this.callDataSourceEvents('afterchanges', this.data);
1431
1744
  }
1432
1745
  }
@@ -1436,7 +1749,9 @@ angular.module('datasourcejs', [])
1436
1749
  if (callback) {
1437
1750
  callback();
1438
1751
  }
1439
- this.postDeleteData = null;
1752
+ if (!batchMode) {
1753
+ this.postDeleteData = null;
1754
+ }
1440
1755
  }.bind(this));
1441
1756
 
1442
1757
  return resetFunc;
@@ -1561,7 +1876,7 @@ angular.module('datasourcejs', [])
1561
1876
 
1562
1877
  this.updateActive = function(from) {
1563
1878
  for (var key in from) {
1564
- if (from.hasOwnProperty(key)) {
1879
+ if (from.hasOwnProperty(key) && key != "__status") {
1565
1880
  this.active[key] = from[key];
1566
1881
  }
1567
1882
  }
@@ -1684,7 +1999,7 @@ angular.module('datasourcejs', [])
1684
1999
  /**
1685
2000
  * Insert or update based on the the datasource state
1686
2001
  */
1687
- this.post = function(onSuccess, onError, silent) {
2002
+ this.post = function(onSuccess, onError, silent, keepBuffer) {
1688
2003
 
1689
2004
  if (!silent && this.missingRequiredField())
1690
2005
  return;
@@ -1692,13 +2007,28 @@ angular.module('datasourcejs', [])
1692
2007
  if (!silent && this.hasInvalidField())
1693
2008
  return;
1694
2009
 
2010
+ if (!keepBuffer) {
2011
+ this.batchServiceData = [];
2012
+ }
2013
+
1695
2014
  this.lastAction = "post"; //TRM
1696
2015
 
1697
2016
  this.busy = true;
1698
2017
 
1699
2018
  if (this.inserting) {
1700
2019
  // Make a new request to persist the new item
1701
- this.insert(this.active, function(obj, hotData) {
2020
+ this.insert(this.active, function(obj, hotData, batchPostponed) {
2021
+ if (batchPostponed) {
2022
+ if (this.dependentData && !this.dependentLazyPost && !this.batchPost) {
2023
+ this.flushDependencies(() => {
2024
+ this.performBatchPost(() => {
2025
+ this.post(onSuccess, onError, silent, true);
2026
+ });
2027
+ }, true);
2028
+
2029
+ return;
2030
+ }
2031
+ }
1702
2032
  // In case of success add the new inserted value at
1703
2033
  // the end of the array
1704
2034
 
@@ -1710,7 +2040,7 @@ angular.module('datasourcejs', [])
1710
2040
  obj.__$id = this.active.__$id;
1711
2041
  }
1712
2042
 
1713
- var func = function() {
2043
+ var func = function(resetFunctions) {
1714
2044
  // The new object is now the active
1715
2045
  this.active = obj;
1716
2046
 
@@ -1729,13 +2059,19 @@ angular.module('datasourcejs', [])
1729
2059
  if (this.events.memorycreate && !hotData) {
1730
2060
  this.callDataSourceEvents('memorycreate', this.active);
1731
2061
  }
2062
+
2063
+ if (resetFunctions) {
2064
+ for (let i =0;i<resetFunctions.length;i++) {
2065
+ resetFunctions[i]();
2066
+ }
2067
+ }
1732
2068
  }.bind(this);
1733
2069
 
1734
2070
  var proceed = function () {
1735
2071
  this.data.push(obj);
1736
2072
 
1737
2073
  if (this.dependentData && !this.dependentLazyPost && !this.batchPost) {
1738
- this.flushDependencies(func);
2074
+ this.flushDependencies(func, false);
1739
2075
  } else {
1740
2076
  func();
1741
2077
  }
@@ -1760,8 +2096,18 @@ angular.module('datasourcejs', [])
1760
2096
 
1761
2097
  } else if (this.editing) {
1762
2098
  // Make a new request to update the modified item
1763
- this.update(this.active, function(obj, hotData) {
2099
+ this.update(this.active, function(obj, hotData, batchPostponed) {
2100
+ if (batchPostponed) {
2101
+ if (this.dependentData && !this.dependentLazyPost && !this.batchPost) {
2102
+ this.flushDependencies(() => {
2103
+ this.performBatchPost(() => {
2104
+ this.post(onSuccess, onError, silent, true);
2105
+ });
2106
+ }, batchPostponed);
1764
2107
 
2108
+ return;
2109
+ }
2110
+ }
1765
2111
  var odataFiles;
1766
2112
 
1767
2113
  if (hotData) {
@@ -1825,7 +2171,7 @@ angular.module('datasourcejs', [])
1825
2171
  }
1826
2172
  }.bind(this));
1827
2173
 
1828
- var back = function() {
2174
+ var back = function(resetFunctions) {
1829
2175
 
1830
2176
  if (foundRow) {
1831
2177
  this.handleAfterCallBack(this.onAfterUpdate);
@@ -1836,11 +2182,17 @@ angular.module('datasourcejs', [])
1836
2182
  if (onSuccess) {
1837
2183
  onSuccess(this.active);
1838
2184
  }
2185
+
2186
+ if (resetFunctions) {
2187
+ for (let i =0;i<resetFunctions.length;i++) {
2188
+ resetFunctions[i]();
2189
+ }
2190
+ }
1839
2191
  }.bind(this);
1840
2192
 
1841
- var func = function() {
2193
+ var func = function(resetFunctions) {
1842
2194
  if (!hotData) {
1843
- back();
2195
+ back(resetFunctions);
1844
2196
  } else {
1845
2197
  if (odataFiles && odataFiles.length > 0) {
1846
2198
  this.sendODataFiles(odataFiles, foundRow, function (result) {
@@ -1849,10 +2201,10 @@ angular.module('datasourcejs', [])
1849
2201
  if (this.events.update && hotData) {
1850
2202
  this.callDataSourceEvents('update', foundRow);
1851
2203
  }
1852
- back();
2204
+ back(resetFunctions);
1853
2205
  }.bind(this));
1854
2206
  } else {
1855
- back();
2207
+ back(resetFunctions);
1856
2208
  }
1857
2209
  }
1858
2210
  }.bind(this);
@@ -2219,7 +2571,7 @@ angular.module('datasourcejs', [])
2219
2571
  let childrensDs = this.dependentData && this.dependentData.filter( ds => ds.inserting || ds.editing );
2220
2572
  !childrensDs || childrensDs.forEach( ds => ds.cancel() );
2221
2573
 
2222
- this.changeTitle();
2574
+ this.noticeStatusChange();
2223
2575
  }.bind(this))
2224
2576
  };
2225
2577
 
@@ -2243,6 +2595,7 @@ angular.module('datasourcejs', [])
2243
2595
  this.cleanDependentBuffer();
2244
2596
  });
2245
2597
  }
2598
+ this.batchServiceData = [];
2246
2599
  };
2247
2600
 
2248
2601
  this.removeODataFields = function(obj) {
@@ -2282,7 +2635,7 @@ angular.module('datasourcejs', [])
2282
2635
  // Get an ajax promise
2283
2636
  var url = this.entity;
2284
2637
  url += (this.entity.endsWith('/')) ? '__new__' : '/__new__';
2285
- this.$promise = $http({
2638
+ this.$promise = $httpLegacy({
2286
2639
  method: "GET",
2287
2640
  url: this.removeSlash((window.hostApp || "") + url),
2288
2641
  headers: this.headers
@@ -2356,6 +2709,11 @@ angular.module('datasourcejs', [])
2356
2709
 
2357
2710
  };
2358
2711
 
2712
+ this.noticeStatusChange = function() {
2713
+ this.changeTitle();
2714
+ this.handleBeforeCallBack(this.onChangeStatus);
2715
+ };
2716
+
2359
2717
  this.changeTitle = function() {
2360
2718
  if (!$('#starter').length || $('#starter').attr('primary-datasource') !== this.name) {
2361
2719
  return;
@@ -2383,6 +2741,17 @@ angular.module('datasourcejs', [])
2383
2741
  this.active.__$id = uuid();
2384
2742
  }
2385
2743
 
2744
+ if (this.children && this.children.length) {
2745
+ let keys = this.getKeyValues(this.active);
2746
+ for (let key in keys) {
2747
+ if (keys.hasOwnProperty(key)) {
2748
+ if ((keys[key] == null || keys[key] == undefined) && key == '_objectKey') {
2749
+ this.active[key] = "$autogenerated$" + this.uuidv4();
2750
+ }
2751
+ }
2752
+ }
2753
+ }
2754
+
2386
2755
  this.inserting = true;
2387
2756
 
2388
2757
  if (this.onStartInserting) {
@@ -2397,7 +2766,7 @@ angular.module('datasourcejs', [])
2397
2766
  }
2398
2767
 
2399
2768
  this.resetFieldsStatus();
2400
- this.changeTitle();
2769
+ this.noticeStatusChange();
2401
2770
 
2402
2771
  }.bind(this));
2403
2772
  };
@@ -2425,7 +2794,7 @@ angular.module('datasourcejs', [])
2425
2794
  this.callDataSourceEvents('updating', this.active);
2426
2795
  }
2427
2796
  this.resetFieldsStatus();
2428
- this.changeTitle();
2797
+ this.noticeStatusChange();
2429
2798
  };
2430
2799
 
2431
2800
  this.removeSilent = function(object, onSuccess, onError) {
@@ -2447,7 +2816,10 @@ angular.module('datasourcejs', [])
2447
2816
 
2448
2817
  var keyObj = this.getKeyValues(object, forceDelete);
2449
2818
 
2450
- callback = callback || function(empty, hotData) {
2819
+ callback = callback || function(empty, hotData, batchPostponed) {
2820
+ if (batchPostponed) {
2821
+ return;
2822
+ }
2451
2823
  // For each row data
2452
2824
  for (var i = 0; i < this.data.length; i++) {
2453
2825
  // current object match with the same
@@ -2535,7 +2907,7 @@ angular.module('datasourcejs', [])
2535
2907
  if ((this.dependentLazyPost || this.batchPost) && !forceDelete) {
2536
2908
  callback();
2537
2909
  } else {
2538
- service.remove(this.getDeletionURL(object, forceDelete)).$promise.error(onError).then(callback);
2910
+ service.remove(this.getDeletionURL(object, forceDelete), object).$promise.error(onError).then(callback);
2539
2911
  }
2540
2912
  }
2541
2913
  }.bind(this);
@@ -2687,6 +3059,9 @@ angular.module('datasourcejs', [])
2687
3059
  } else {
2688
3060
  this.offset = parseInt(this.offset) + 1;
2689
3061
  }
3062
+ if (this._savedProps && this._savedProps.params) {
3063
+ delete this._savedProps.params.$skip;
3064
+ }
2690
3065
  this.fetch(this._savedProps, {
2691
3066
  success: function(data) {
2692
3067
  if (!data || data.length < parseInt(this.rowsPerPage)) {
@@ -2718,7 +3093,9 @@ angular.module('datasourcejs', [])
2718
3093
  this.prevPage = function() {
2719
3094
  if (!this.append && !this.preppend) {
2720
3095
  this.offset = parseInt(this.offset) - this.data.length;
2721
-
3096
+ if (this._savedProps && this._savedProps.params) {
3097
+ delete this._savedProps.params.$skip;
3098
+ }
2722
3099
  if (this.offset < 0) {
2723
3100
  this.offset = 0;
2724
3101
  } else if (this.offset >= 0) {
@@ -3134,6 +3511,56 @@ angular.module('datasourcejs', [])
3134
3511
  });
3135
3512
  }
3136
3513
 
3514
+ this.getParametersBatchExpression = function(parentId) {
3515
+ var expression = "";
3516
+
3517
+ var parameters;
3518
+
3519
+ var obj;
3520
+
3521
+ parameters = this.parametersExpression;
3522
+ let ds = eval(this.dependentLazyPost);
3523
+
3524
+ if (ds) {
3525
+ var arr = ds.getAllData();
3526
+ if (ds.active && ds.active.__$id == parentId) {
3527
+ obj = ds.active;
3528
+ } else {
3529
+ for (var i = 0; i < arr.length; i++) {
3530
+ if (arr[i].__$id == parentId) {
3531
+ obj = arr[i];
3532
+ break;
3533
+ }
3534
+ }
3535
+ }
3536
+ }
3537
+
3538
+ if (parameters && parameters.length > 0) {
3539
+ var parts = parameters.split(";")
3540
+ for (var i=0;i<parts.length;i++) {
3541
+ var part = parts[i];
3542
+ var binary = part.split("=");
3543
+ if (binary.length == 2) {
3544
+ var value = binary[1];
3545
+ if (binary[1].match(DEP_PATTERN)) {
3546
+ var g = DEP_PATTERN.exec(value);
3547
+ if (g[1].indexOf(".active.") != -1) {
3548
+ var field = g[1].replace(this.dependentLazyPost + ".active.", "");
3549
+ if (obj) {
3550
+ if (expression != '') {
3551
+ expression += ",";
3552
+ }
3553
+ expression = binary[0] + ":" + "$"+parentId+"."+field;
3554
+ }
3555
+ }
3556
+ }
3557
+ }
3558
+ }
3559
+ }
3560
+
3561
+ return expression;
3562
+ }
3563
+
3137
3564
  this.removeSlash = function(u) {
3138
3565
  if (u.indexOf("http://") == 0) {
3139
3566
  return "http://" + u.substring(7).split("//").join("/");
@@ -3834,7 +4261,7 @@ angular.module('datasourcejs', [])
3834
4261
  var filterClause;
3835
4262
 
3836
4263
  var g = DEP_PATTERN.exec(binaryExpression[1]);
3837
- if (this.isEmpty(binary[1]) && this.dependentLazyPost && g[1] && g[1].startsWith(this.dependentLazyPost+".")) {
4264
+ if ((this.isEmpty(binary[1]) || this.isAutoGeneratedValue(binary[1])) && this.dependentLazyPost && g[1] && g[1].startsWith(this.dependentLazyPost+".")) {
3838
4265
  if (this.parametersNullStrategy == "clean" || this.parametersNullStrategy == "default") {
3839
4266
  cleanData = true;
3840
4267
  var dds = eval(this.dependentLazyPost);
@@ -4406,6 +4833,7 @@ angular.module('datasourcejs', [])
4406
4833
  dts.onAfterUpdate = props.onAfterUpdate;
4407
4834
  dts.onBeforeDelete = props.onBeforeDelete;
4408
4835
  dts.onAfterDelete = props.onAfterDelete;
4836
+ dts.onChangeStatus = props.onChangeStatus;
4409
4837
  dts.onGET = props.onGet,
4410
4838
  dts.onPOST = props.onPost,
4411
4839
  dts.onPUT = props.onPut,
@@ -4551,6 +4979,8 @@ function(DatasetManager, $timeout, $parse, Notification, $translate, $location,
4551
4979
  };
4552
4980
  }])
4553
4981
 
4982
+ let datasourceRepeat = 1;
4983
+
4554
4984
  app.directive('crnRepeat', function(DatasetManager, $compile, $parse, $injector, $rootScope) {
4555
4985
  return {
4556
4986
  restrict: 'A',
@@ -4558,21 +4988,22 @@ app.directive('crnRepeat', function(DatasetManager, $compile, $parse, $injector,
4558
4988
  terminal: true,
4559
4989
  link: function(scope, element, attrs, controllers, transclude) {
4560
4990
 
4991
+ datasourceRepeat++;
4561
4992
  if (attrs.crnRepeat) {
4562
4993
  scope.data = DatasetManager.datasets;
4563
4994
  if (scope.data[attrs.crnRepeat]) {
4564
- scope.datasourceRepeat = scope.data[attrs.crnRepeat];
4995
+ scope['datasourceRepeat' + datasourceRepeat] = scope.data[attrs.crnRepeat];
4565
4996
  } else {
4566
- scope.datasourceRepeat = {};
4567
- scope.datasourceRepeat.data = $parse(attrs.crnRepeat)(scope);
4997
+ scope['datasourceRepeat' + datasourceRepeat] = {};
4998
+ scope['datasourceRepeat' + datasourceRepeat].data = $parse(attrs.crnRepeat)(scope);
4568
4999
  }
4569
- element.attr('ng-repeat', 'rowData in datasourceRepeat.data');
5000
+ element.attr('ng-repeat', 'rowData in datasourceRepeat' + datasourceRepeat + '.data');
4570
5001
 
4571
5002
  }
4572
5003
 
4573
5004
  var tagName = element[0].tagName;
4574
5005
  $compile(element, null, 9999998)(scope);
4575
- scope.$watchCollection('datasourceRepeat.data', function (newVal, oldVal) {
5006
+ scope.$watchCollection('datasourceRepeat' + datasourceRepeat + '.data', function (newVal, oldVal) {
4576
5007
  if (tagName.toLowerCase() == "ion-slide") {
4577
5008
  var $ionicSlideBoxDelegate = $injector.get('$ionicSlideBoxDelegate');
4578
5009
  $ionicSlideBoxDelegate.update();