@sumaris-net/ngx-components 1.21.0-beta8 → 1.21.1

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.
Files changed (86) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +535 -1191
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/doc/changelog.md +12 -0
  6. package/esm2015/public_api.js +3 -8
  7. package/esm2015/src/app/core/account/account.js +2 -2
  8. package/esm2015/src/app/core/auth/form/form-auth.js +4 -2
  9. package/esm2015/src/app/core/form/editor.class.js +52 -20
  10. package/esm2015/src/app/core/form/entity-editor-modal.class.js +17 -6
  11. package/esm2015/src/app/core/form/entity-editor.class.js +1 -1
  12. package/esm2015/src/app/core/form/form.class.js +66 -33
  13. package/esm2015/src/app/core/graphql/graphql.service.js +5 -3
  14. package/esm2015/src/app/core/icon/icon.component.js +2 -5
  15. package/esm2015/src/app/core/menu/menu.component.js +2 -2
  16. package/esm2015/src/app/core/services/local-settings.service.js +2 -2
  17. package/esm2015/src/app/core/table/table.class.js +18 -23
  18. package/esm2015/src/app/shared/functions.js +1 -60
  19. package/esm2015/src/app/shared/material/autocomplete/material.autocomplete.js +5 -4
  20. package/esm2015/src/app/shared/material/autocomplete/testing/autocomplete.test.js +10 -7
  21. package/esm2015/src/app/shared/material/chips/material.chips.js +3 -2
  22. package/esm2015/src/app/shared/material/chips/testing/chips.test.js +3 -2
  23. package/esm2015/src/app/shared/material/datetime/material.date.js +3 -2
  24. package/esm2015/src/app/shared/material/datetime/material.datetime.js +3 -2
  25. package/esm2015/src/app/shared/observables.js +13 -7
  26. package/esm2015/src/app/shared/pipes/arrays.pipe.js +1 -1
  27. package/esm2015/src/app/shared/pipes/form.pipes.js +4 -6
  28. package/esm2015/src/app/shared/pipes/highlight.pipe.js +4 -4
  29. package/esm2015/src/app/shared/pipes/string.pipes.js +7 -18
  30. package/esm2015/src/app/shared/services/memory-entity-service.class.js +13 -1
  31. package/esm2015/src/app/shared/services.js +61 -0
  32. package/esm2015/src/app/shared/types.js +1 -1
  33. package/esm2015/src/app/social/social.errors.js +2 -5
  34. package/esm2015/src/app/social/social.module.js +15 -10
  35. package/esm2015/src/app/social/user-event/user-event.model.js +2 -58
  36. package/esm2015/src/app/social/user-event/user-event.service.js +167 -293
  37. package/esm2015/src/app/social/user-event/user-events.table.js +12 -17
  38. package/esm2015/sumaris-net.ngx-components.js +6 -8
  39. package/fesm2015/sumaris-net.ngx-components.js +437 -990
  40. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  41. package/package.json +3 -2
  42. package/public_api.d.ts +2 -7
  43. package/src/app/core/auth/form/form-auth.d.ts +1 -1
  44. package/src/app/core/form/editor.class.d.ts +38 -12
  45. package/src/app/core/form/entity-editor-modal.class.d.ts +1 -0
  46. package/src/app/core/form/entity-editor.class.d.ts +6 -2
  47. package/src/app/core/form/form.class.d.ts +32 -19
  48. package/src/app/core/icon/icon.component.d.ts +4 -4
  49. package/src/app/core/table/table.class.d.ts +15 -14
  50. package/src/app/shared/functions.d.ts +0 -9
  51. package/src/app/shared/material/autocomplete/testing/autocomplete.test.d.ts +1 -2
  52. package/src/app/shared/material/badge/badge-icon.test.d.ts +1 -1
  53. package/src/app/shared/observables.d.ts +1 -0
  54. package/src/app/shared/pipes/form.pipes.d.ts +1 -2
  55. package/src/app/shared/services/memory-entity-service.class.d.ts +6 -0
  56. package/src/app/shared/services.d.ts +9 -0
  57. package/src/app/shared/types.d.ts +0 -4
  58. package/src/app/social/social.errors.d.ts +0 -3
  59. package/src/app/social/social.module.d.ts +0 -8
  60. package/src/app/social/user-event/user-event.model.d.ts +6 -51
  61. package/src/app/social/user-event/user-event.service.d.ts +51 -79
  62. package/src/app/social/user-event/user-events.table.d.ts +6 -6
  63. package/src/assets/i18n/en-US.json +2 -15
  64. package/src/assets/i18n/en.json +2 -15
  65. package/src/assets/i18n/fr.json +1 -14
  66. package/src/theme/_ngx-components.scss +0 -7
  67. package/sumaris-net.ngx-components.d.ts +5 -7
  68. package/sumaris-net.ngx-components.metadata.json +1 -1
  69. package/esm2015/src/app/social/job/job.model.js +0 -24
  70. package/esm2015/src/app/social/job/job.module.js +0 -25
  71. package/esm2015/src/app/social/job/job.service.js +0 -53
  72. package/esm2015/src/app/social/job/progression/job-progression.component.js +0 -192
  73. package/esm2015/src/app/social/job/progression/job-progression.list.js +0 -20
  74. package/esm2015/src/app/social/message/message.module.js +0 -25
  75. package/esm2015/src/app/social/user-event/notification/user-event-notification.component.js +0 -92
  76. package/esm2015/src/app/social/user-event/notification/user-event-notification.list.js +0 -39
  77. package/esm2015/src/app/social/user-event/user-event.module.js +0 -28
  78. package/src/app/social/job/job.model.d.ts +0 -32
  79. package/src/app/social/job/job.module.d.ts +0 -2
  80. package/src/app/social/job/job.service.d.ts +0 -23
  81. package/src/app/social/job/progression/job-progression.component.d.ts +0 -43
  82. package/src/app/social/job/progression/job-progression.list.d.ts +0 -12
  83. package/src/app/social/message/message.module.d.ts +0 -2
  84. package/src/app/social/user-event/notification/user-event-notification.component.d.ts +0 -25
  85. package/src/app/social/user-event/notification/user-event-notification.list.d.ts +0 -20
  86. package/src/app/social/user-event/user-event.module.d.ts +0 -2
@@ -46,7 +46,7 @@
46
46
  var SPACE_PLACEHOLDER_CHAR = '\u2000';
47
47
  var KEYBOARD_HIDE_DELAY_MS = 250; // 1s
48
48
 
49
- /******************************************************************************
49
+ /*! *****************************************************************************
50
50
  Copyright (c) Microsoft Corporation.
51
51
 
52
52
  Permission to use, copy, modify, and/or distribute this software for any
@@ -208,11 +208,7 @@
208
208
  var __createBinding = Object.create ? (function (o, m, k, k2) {
209
209
  if (k2 === undefined)
210
210
  k2 = k;
211
- var desc = Object.getOwnPropertyDescriptor(m, k);
212
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
213
- desc = { enumerable: true, get: function () { return m[k]; } };
214
- }
215
- Object.defineProperty(o, k2, desc);
211
+ Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
216
212
  }) : (function (o, m, k, k2) {
217
213
  if (k2 === undefined)
218
214
  k2 = k;
@@ -367,11 +363,6 @@
367
363
  throw new TypeError("Cannot write private member to an object whose class did not declare it");
368
364
  return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
369
365
  }
370
- function __classPrivateFieldIn(state, receiver) {
371
- if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function"))
372
- throw new TypeError("Cannot use 'in' operator on non-object");
373
- return typeof state === "function" ? receiver === state : state.has(receiver);
374
- }
375
366
 
376
367
  function isNil(obj) {
377
368
  return obj === undefined || obj === null;
@@ -509,67 +500,6 @@
509
500
  function removeDiacritics(text) {
510
501
  return text.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
511
502
  }
512
- function suggestFromArray(items, value, opts) {
513
- var _this = this;
514
- if (isNotNil(value) && typeof value === 'object')
515
- return { data: [value] };
516
- value = (typeof value === 'string' && value !== '*') && value.toUpperCase() || undefined;
517
- var keys = opts && (opts.searchAttribute && [opts.searchAttribute] || opts.searchAttributes) || ['label'];
518
- if (!items) {
519
- return { data: [], total: 0 };
520
- }
521
- // Filter items
522
- var filteredItems = items;
523
- if (isNotNilOrBlank(value)) {
524
- // If wildcard, search using regexp
525
- if (value.indexOf('*') !== -1) {
526
- value = value.replace(/[*]+/g, '.*');
527
- filteredItems = filteredItems.filter(function (v) { return keys.findIndex(function (key) { return matchUpperCase(getPropertyByPathAsString(v, key), value); }) !== -1; });
528
- }
529
- // Else (no wildcard), search using startsWith
530
- else {
531
- filteredItems = filteredItems.filter(function (v) { return keys.findIndex(function (key) { return startsWithUpperCase(getPropertyByPathAsString(v, key), value); }) !== -1; });
532
- }
533
- }
534
- // Exclude ids
535
- if (isNotEmptyArray(opts === null || opts === void 0 ? void 0 : opts.excludedIds)) {
536
- filteredItems = filteredItems.filter(function (v) { return !opts.excludedIds.includes(+v['id']); });
537
- }
538
- // Sort
539
- if (!opts || opts.skipSort !== true) {
540
- // Make to copy input items, before sorting (if not yet already done)
541
- if (filteredItems === items)
542
- filteredItems = filteredItems.slice();
543
- // Sort by keys
544
- filteredItems.sort(propertiesPathComparator(keys));
545
- }
546
- var total = filteredItems.length || 0;
547
- // Pagination (truncate if need)
548
- var pageData = filteredItems;
549
- if (opts) {
550
- if ((opts.offset || 0) > 0) {
551
- pageData = pageData.slice(opts.offset);
552
- }
553
- if (isNotNil(opts.size) && pageData.length > opts.size) {
554
- pageData = pageData.slice(0, opts.size);
555
- }
556
- }
557
- var result = {
558
- data: pageData,
559
- total: total
560
- };
561
- // Add fetch more capability, if total was fetched
562
- var nextOffset = (opts && opts.offset || 0) + pageData.length;
563
- if (nextOffset < total) {
564
- result.fetchMore = function (_) { return __awaiter(_this, void 0, void 0, function () {
565
- return __generator(this, function (_b) {
566
- return [2 /*return*/, suggestFromArray(filteredItems, undefined /*OPTIMISATION: already applied*/, Object.assign(Object.assign({}, opts), { offset: nextOffset, skipSort: true, excludedIds: undefined // OPTIMISATION: already filtered
567
- }))];
568
- });
569
- }); };
570
- }
571
- return result;
572
- }
573
503
  function suggestFromStringArray(values, value, options) {
574
504
  value = (typeof value === 'string' && value !== '*') && value.toUpperCase() || undefined;
575
505
  if (isNilOrBlank(value))
@@ -1117,11 +1047,11 @@
1117
1047
  }, null);
1118
1048
  }
1119
1049
  function firstTrue(obs) {
1120
- return obs.pipe(operators.first(function (v) { return v === true; }), operators.map(function (_) { }) // Convert to void
1050
+ return obs.pipe(operators.first(function (value) { return value === true; }), operators.map(function (_) { }) // Convert to void
1121
1051
  );
1122
1052
  }
1123
1053
  function firstFalse(obs) {
1124
- return obs.pipe(operators.first(function (v) { return v === false; }), operators.map(function (_) { }) // Convert to void
1054
+ return obs.pipe(operators.first(function (value) { return value === false; }), operators.map(function (_) { }) // Convert to void
1125
1055
  );
1126
1056
  }
1127
1057
  /**
@@ -1162,14 +1092,13 @@
1162
1092
  }
1163
1093
  function waitForTrue(observable, opts) {
1164
1094
  return __awaiter(this, void 0, void 0, function () {
1165
- var firstTrueObservable, $timeout;
1095
+ var $timeout;
1166
1096
  return __generator(this, function (_a) {
1167
- firstTrueObservable = firstTrue(observable);
1168
1097
  // Timeout (+ dueTime)
1169
1098
  if (opts && opts.timeout > 0) {
1170
1099
  $timeout = rxjs.timer(opts.timeout);
1171
1100
  return [2 /*return*/, rxjs.merge(rxjs.timer(opts.dueTime || 0)
1172
- .pipe(operators.switchMap(function () { return firstTrueObservable; }), operators.takeUntil($timeout)), $timeout
1101
+ .pipe(operators.switchMap(function () { return firstTrue(observable); }), operators.takeUntil($timeout)), $timeout
1173
1102
  .pipe(operators.map(function () {
1174
1103
  throw new Error("Timeout ready() - after " + opts.timeout + "ms");
1175
1104
  })))
@@ -1178,10 +1107,19 @@
1178
1107
  // dueTime (without timeout)
1179
1108
  if (opts && opts.dueTime > 0) {
1180
1109
  return [2 /*return*/, rxjs.timer(opts.dueTime)
1181
- .pipe(operators.switchMap(function () { return firstTrueObservable; }))
1110
+ .pipe(operators.switchMap(function () { return firstTrue(observable); }))
1182
1111
  .toPromise()];
1183
1112
  }
1184
- return [2 /*return*/, firstTrueObservable.toPromise()];
1113
+ return [2 /*return*/, firstTrue(observable).toPromise()];
1114
+ });
1115
+ });
1116
+ }
1117
+ function waitForFalse(observable, opts) {
1118
+ return __awaiter(this, void 0, void 0, function () {
1119
+ return __generator(this, function (_a) {
1120
+ return [2 /*return*/, waitForTrue(
1121
+ // Inverse the logic
1122
+ observable.pipe(operators.map(function (v) { return v === false; })), opts)];
1185
1123
  });
1186
1124
  });
1187
1125
  }
@@ -1386,6 +1324,68 @@
1386
1324
  return _cache.mobile;
1387
1325
  };
1388
1326
 
1327
+ function suggestFromArray(items, value, opts) {
1328
+ var _this = this;
1329
+ if (isNotNil(value) && typeof value === 'object')
1330
+ return { data: [value] };
1331
+ value = (typeof value === 'string' && value !== '*') && value.toUpperCase() || undefined;
1332
+ var keys = opts && (opts.searchAttribute && [opts.searchAttribute] || opts.searchAttributes) || ['label'];
1333
+ if (!items) {
1334
+ return { data: [], total: 0 };
1335
+ }
1336
+ // Filter items
1337
+ var filteredItems = items;
1338
+ if (isNotNilOrBlank(value)) {
1339
+ // If wildcard, search using regexp
1340
+ if (value.indexOf('*') !== -1) {
1341
+ value = value.replace(/[*]+/g, '.*');
1342
+ filteredItems = filteredItems.filter(function (v) { return keys.findIndex(function (key) { return matchUpperCase(getPropertyByPathAsString(v, key), value); }) !== -1; });
1343
+ }
1344
+ // Else (no wildcard), search using startsWith
1345
+ else {
1346
+ filteredItems = filteredItems.filter(function (v) { return keys.findIndex(function (key) { return startsWithUpperCase(getPropertyByPathAsString(v, key), value); }) !== -1; });
1347
+ }
1348
+ }
1349
+ // Exclude ids
1350
+ if (isNotEmptyArray(opts === null || opts === void 0 ? void 0 : opts.excludedIds)) {
1351
+ filteredItems = filteredItems.filter(function (v) { return !opts.excludedIds.includes(+v['id']); });
1352
+ }
1353
+ // Sort
1354
+ if (!opts || opts.skipSort !== true) {
1355
+ // Make to copy input items, before sorting (if not yet already done)
1356
+ if (filteredItems === items)
1357
+ filteredItems = filteredItems.slice();
1358
+ // Sort by keys
1359
+ filteredItems.sort(propertiesPathComparator(keys));
1360
+ }
1361
+ var total = filteredItems.length || 0;
1362
+ // Pagination (truncate if need)
1363
+ var pageData = filteredItems;
1364
+ if (opts) {
1365
+ if ((opts.offset || 0) > 0) {
1366
+ pageData = pageData.slice(opts.offset);
1367
+ }
1368
+ if (isNotNil(opts.size) && pageData.length > opts.size) {
1369
+ pageData = pageData.slice(0, opts.size);
1370
+ }
1371
+ }
1372
+ var result = {
1373
+ data: pageData,
1374
+ total: total
1375
+ };
1376
+ // Add fetch more capability, if total was fetched
1377
+ var nextOffset = (opts && opts.offset || 0) + pageData.length;
1378
+ if (nextOffset < total) {
1379
+ result.fetchMore = function (_) { return __awaiter(_this, void 0, void 0, function () {
1380
+ return __generator(this, function (_a) {
1381
+ return [2 /*return*/, suggestFromArray(filteredItems, undefined /*OPTIMISATION: already applied*/, Object.assign(Object.assign({}, opts), { offset: nextOffset, skipSort: true, excludedIds: undefined // OPTIMISATION: already filtered
1382
+ }))];
1383
+ });
1384
+ }); };
1385
+ }
1386
+ return result;
1387
+ }
1388
+
1389
1389
  var MatAutocompleteConfigHolder = /** @class */ (function () {
1390
1390
  function MatAutocompleteConfigHolder(options) {
1391
1391
  this.options = options;
@@ -1706,11 +1706,11 @@
1706
1706
  // Search text (no distinctUntilChanged() because of the debounceTime() pipe)
1707
1707
  this.formControl.valueChanges
1708
1708
  .pipe(operators.filter(function (value) { return _this.enabled && isNotNilString(value); }),
1709
- // Mark as loading (to show loading spinner) - earlier as possible, so before the debounce time
1709
+ // Mark as loading (to show loading spinner) - as soon as possible, and before debounceTime
1710
1710
  operators.tap(function (_) { return _this.showLoadingSpinner && _this.markAsLoading(); }),
1711
1711
  // Filter if not enough character
1712
1712
  operators.filter(function (value) {
1713
- if (value.length <= _this.suggestLengthThreshold) {
1713
+ if (((value === null || value === void 0 ? void 0 : value.length) || 0) < _this.suggestLengthThreshold) {
1714
1714
  // Update display value, to enable the message "not enough characters"
1715
1715
  _this.displayValue = value;
1716
1716
  return false;
@@ -2709,9 +2709,9 @@
2709
2709
  var cleanedSearchText = removeDiacritics(searchRegexp).toUpperCase();
2710
2710
  var index = removeDiacritics(value.toUpperCase()).indexOf(cleanedSearchText);
2711
2711
  if (index !== -1) {
2712
- return value.substr(0, index - 1) +
2713
- '<b>' + value.substr(index, cleanedSearchText.length) + '</b>' +
2714
- value.substr(index + cleanedSearchText.length);
2712
+ return value.substring(0, index - 1) +
2713
+ '<b>' + value.substring(index, cleanedSearchText.length) + '</b>' +
2714
+ value.substring(index + cleanedSearchText.length);
2715
2715
  }
2716
2716
  return value;
2717
2717
  }
@@ -3159,12 +3159,10 @@
3159
3159
  };
3160
3160
  return IsNotNilOrBlankPipe;
3161
3161
  }());
3162
- IsNotNilOrBlankPipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function IsNotNilOrBlankPipe_Factory() { return new IsNotNilOrBlankPipe(); }, token: IsNotNilOrBlankPipe, providedIn: "root" });
3163
3162
  IsNotNilOrBlankPipe.decorators = [
3164
3163
  { type: i0.Pipe, args: [{
3165
3164
  name: 'isNotNilOrBlank'
3166
- },] },
3167
- { type: i0.Injectable, args: [{ providedIn: 'root' },] }
3165
+ },] }
3168
3166
  ];
3169
3167
  var IsNilOrBlankPipe = /** @class */ (function () {
3170
3168
  function IsNilOrBlankPipe() {
@@ -3174,12 +3172,10 @@
3174
3172
  };
3175
3173
  return IsNilOrBlankPipe;
3176
3174
  }());
3177
- IsNilOrBlankPipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function IsNilOrBlankPipe_Factory() { return new IsNilOrBlankPipe(); }, token: IsNilOrBlankPipe, providedIn: "root" });
3178
3175
  IsNilOrBlankPipe.decorators = [
3179
3176
  { type: i0.Pipe, args: [{
3180
3177
  name: 'isNilOrBlank'
3181
- },] },
3182
- { type: i0.Injectable, args: [{ providedIn: 'root' },] }
3178
+ },] }
3183
3179
  ];
3184
3180
  var ToStringPipe = /** @class */ (function () {
3185
3181
  function ToStringPipe() {
@@ -3189,12 +3185,10 @@
3189
3185
  };
3190
3186
  return ToStringPipe;
3191
3187
  }());
3192
- ToStringPipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function ToStringPipe_Factory() { return new ToStringPipe(); }, token: ToStringPipe, providedIn: "root" });
3193
3188
  ToStringPipe.decorators = [
3194
3189
  { type: i0.Pipe, args: [{
3195
3190
  name: 'toString'
3196
- },] },
3197
- { type: i0.Injectable, args: [{ providedIn: 'root' },] }
3191
+ },] }
3198
3192
  ];
3199
3193
  var StrLengthPipe = /** @class */ (function () {
3200
3194
  function StrLengthPipe() {
@@ -3204,12 +3198,10 @@
3204
3198
  };
3205
3199
  return StrLengthPipe;
3206
3200
  }());
3207
- StrLengthPipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function StrLengthPipe_Factory() { return new StrLengthPipe(); }, token: StrLengthPipe, providedIn: "root" });
3208
3201
  StrLengthPipe.decorators = [
3209
3202
  { type: i0.Pipe, args: [{
3210
3203
  name: 'strLength'
3211
- },] },
3212
- { type: i0.Injectable, args: [{ providedIn: 'root' },] }
3204
+ },] }
3213
3205
  ];
3214
3206
  var StrIncludesPipe = /** @class */ (function () {
3215
3207
  function StrIncludesPipe() {
@@ -3219,12 +3211,10 @@
3219
3211
  };
3220
3212
  return StrIncludesPipe;
3221
3213
  }());
3222
- StrIncludesPipe.ɵprov = i0.ɵɵdefineInjectable({ factory: function StrIncludesPipe_Factory() { return new StrIncludesPipe(); }, token: StrIncludesPipe, providedIn: "root" });
3223
3214
  StrIncludesPipe.decorators = [
3224
3215
  { type: i0.Pipe, args: [{
3225
3216
  name: 'strIncludes'
3226
- },] },
3227
- { type: i0.Injectable, args: [{ providedIn: 'root' },] }
3217
+ },] }
3228
3218
  ];
3229
3219
 
3230
3220
  var TranslateContextService = /** @class */ (function () {
@@ -4769,7 +4759,7 @@
4769
4759
  function FormGetControlPipe() {
4770
4760
  }
4771
4761
  FormGetControlPipe.prototype.transform = function (form, path) {
4772
- return (form && path && form.get(path) || form);
4762
+ return (form && isNotNil(path) && form.get(path) || form);
4773
4763
  };
4774
4764
  return FormGetControlPipe;
4775
4765
  }());
@@ -4805,8 +4795,7 @@
4805
4795
  },] }
4806
4796
  ];
4807
4797
  var FormGetValuePipe = /** @class */ (function () {
4808
- function FormGetValuePipe(adapter, _ref) {
4809
- this.adapter = adapter;
4798
+ function FormGetValuePipe(_ref) {
4810
4799
  this._ref = _ref;
4811
4800
  this.value = undefined;
4812
4801
  this._lastControl = null;
@@ -4874,7 +4863,6 @@
4874
4863
  },] }
4875
4864
  ];
4876
4865
  FormGetValuePipe.ctorParameters = function () { return [
4877
- { type: FormErrorTranslator },
4878
4866
  { type: i0.ChangeDetectorRef }
4879
4867
  ]; };
4880
4868
 
@@ -5796,10 +5784,10 @@
5796
5784
  return this._tabindex;
5797
5785
  },
5798
5786
  set: function (value) {
5799
- var _this = this;
5800
5787
  if (this._tabindex !== value) {
5801
5788
  this._tabindex = value;
5802
- setTimeout(function () { return _this.updateTabIndex(); });
5789
+ if (!this._writing)
5790
+ this.updateTabIndex();
5803
5791
  }
5804
5792
  },
5805
5793
  enumerable: false,
@@ -6191,10 +6179,10 @@
6191
6179
  return this._tabindex;
6192
6180
  },
6193
6181
  set: function (value) {
6194
- var _this = this;
6195
6182
  if (this._tabindex !== value) {
6196
6183
  this._tabindex = value;
6197
- setTimeout(function () { return _this.updateTabIndex(); });
6184
+ if (!this._writing)
6185
+ this.updateTabIndex();
6198
6186
  }
6199
6187
  },
6200
6188
  enumerable: false,
@@ -12044,7 +12032,7 @@
12044
12032
  Object.defineProperty(LocalSettingsService.prototype, "usageMode", {
12045
12033
  get: function () {
12046
12034
  var _a;
12047
- if (isNil((_a = this._data) === null || _a === void 0 ? void 0 : _a.mobile)) {
12035
+ if (isNil((_a = this._data) === null || _a === void 0 ? void 0 : _a.usageMode)) {
12048
12036
  console.warn("[settings] Accessing to property 'usageMode' BEFORE service started! Please use ready()");
12049
12037
  return isCordova(window) ? 'FIELD' : 'DESK';
12050
12038
  }
@@ -15234,7 +15222,8 @@
15234
15222
  console.debug('[graphql] Apply token authentication to headers');
15235
15223
  this.connectionParams.authToken = token;
15236
15224
  }
15237
- else {
15225
+ // Clean auth token
15226
+ else if (this.connectionParams.authToken) {
15238
15227
  console.debug('[graphql] Remove token authentication from headers');
15239
15228
  delete this.connectionParams.authToken;
15240
15229
  // Clear cache
@@ -15246,7 +15235,8 @@
15246
15235
  console.debug('[graphql] Apply basic authentication to headers');
15247
15236
  this.connectionParams.authBasic = basic;
15248
15237
  }
15249
- else {
15238
+ // Clean auth basic
15239
+ else if (this.connectionParams.authBasic) {
15250
15240
  console.debug('[graphql] Remove basic authentication from headers');
15251
15241
  delete this.connectionParams.authBasic;
15252
15242
  // Clear cache
@@ -19948,12 +19938,12 @@
19948
19938
  var AppForm = /** @class */ (function () {
19949
19939
  function AppForm(injector, form) {
19950
19940
  var _this = this;
19951
- this.error = null;
19941
+ this._subscription = new rxjs.Subscription();
19952
19942
  this._enable = false;
19953
- this._$ready = new rxjs.BehaviorSubject(false);
19954
- this._$loading = new rxjs.BehaviorSubject(true);
19955
19943
  this.i18nFieldPrefix = null;
19956
- this._subscription = new rxjs.Subscription();
19944
+ this.readySubject = new rxjs.BehaviorSubject(false);
19945
+ this.loadingSubject = new rxjs.BehaviorSubject(true);
19946
+ this.errorSubject = new rxjs.BehaviorSubject(undefined);
19957
19947
  this.debug = false;
19958
19948
  this.onCancel = new i0.EventEmitter();
19959
19949
  this.onSubmit = new i0.EventEmitter();
@@ -19983,9 +19973,46 @@
19983
19973
  enumerable: false,
19984
19974
  configurable: true
19985
19975
  });
19976
+ Object.defineProperty(AppForm.prototype, "_$ready", {
19977
+ /**
19978
+ * @deprecated
19979
+ */
19980
+ get: function () {
19981
+ return this.readySubject;
19982
+ },
19983
+ enumerable: false,
19984
+ configurable: true
19985
+ });
19986
+ Object.defineProperty(AppForm.prototype, "_$loading", {
19987
+ /**
19988
+ * @deprecated
19989
+ */
19990
+ get: function () {
19991
+ return this.loadingSubject;
19992
+ },
19993
+ enumerable: false,
19994
+ configurable: true
19995
+ });
19996
+ Object.defineProperty(AppForm.prototype, "error", {
19997
+ get: function () {
19998
+ return this.errorSubject.value;
19999
+ },
20000
+ set: function (error) {
20001
+ this.setError(error);
20002
+ },
20003
+ enumerable: false,
20004
+ configurable: true
20005
+ });
19986
20006
  Object.defineProperty(AppForm.prototype, "loading", {
19987
20007
  get: function () {
19988
- return this._$loading.value;
20008
+ return this.loadingSubject.value;
20009
+ },
20010
+ enumerable: false,
20011
+ configurable: true
20012
+ });
20013
+ Object.defineProperty(AppForm.prototype, "loaded", {
20014
+ get: function () {
20015
+ return !this.loadingSubject.value;
19989
20016
  },
19990
20017
  enumerable: false,
19991
20018
  configurable: true
@@ -20002,7 +20029,8 @@
20002
20029
  });
20003
20030
  Object.defineProperty(AppForm.prototype, "dirty", {
20004
20031
  get: function () {
20005
- return this.form && this.form.dirty;
20032
+ var _a;
20033
+ return ((_a = this.form) === null || _a === void 0 ? void 0 : _a.dirty) || false;
20006
20034
  },
20007
20035
  enumerable: false,
20008
20036
  configurable: true
@@ -20023,7 +20051,8 @@
20023
20051
  });
20024
20052
  Object.defineProperty(AppForm.prototype, "valid", {
20025
20053
  get: function () {
20026
- return this.form && this.form.valid;
20054
+ var _a;
20055
+ return ((_a = this.form) === null || _a === void 0 ? void 0 : _a.valid) || false;
20027
20056
  },
20028
20057
  enumerable: false,
20029
20058
  configurable: true
@@ -20092,17 +20121,19 @@
20092
20121
  };
20093
20122
  AppForm.prototype.ngOnDestroy = function () {
20094
20123
  this._subscription.unsubscribe();
20095
- this.onCancel.complete();
20124
+ this.readySubject.unsubscribe();
20125
+ this.loadingSubject.unsubscribe();
20126
+ this.errorSubject.unsubscribe();
20096
20127
  this.onCancel.unsubscribe();
20097
- this.onSubmit.complete();
20098
20128
  this.onSubmit.unsubscribe();
20099
- this._$ready.complete();
20100
- this._$ready.unsubscribe();
20101
- this._$loading.complete();
20102
- this._$loading.unsubscribe();
20103
20129
  };
20104
20130
  AppForm.prototype.cancel = function () {
20105
- this.onCancel.emit();
20131
+ return __awaiter(this, void 0, void 0, function () {
20132
+ return __generator(this, function (_b) {
20133
+ this.onCancel.emit();
20134
+ return [2 /*return*/];
20135
+ });
20136
+ });
20106
20137
  };
20107
20138
  /**
20108
20139
  *
@@ -20207,22 +20238,14 @@
20207
20238
  this.markForCheck();
20208
20239
  };
20209
20240
  AppForm.prototype.markAsLoading = function (opts) {
20210
- if (this._$loading.value !== true) {
20211
- this._$loading.next(true);
20212
- if (!opts || opts.emitEvent !== false)
20213
- this.markForCheck();
20214
- }
20241
+ this.setLoading(true, opts);
20215
20242
  };
20216
20243
  AppForm.prototype.markAsLoaded = function (opts) {
20217
- if (this._$loading.value !== false) {
20218
- this._$loading.next(false);
20219
- if (!opts || opts.emitEvent !== false)
20220
- this.markForCheck();
20221
- }
20244
+ this.setLoading(false, opts);
20222
20245
  };
20223
20246
  AppForm.prototype.markAsReady = function (opts) {
20224
- if (this._$ready.value !== true) {
20225
- this._$ready.next(true);
20247
+ if (this.readySubject.value !== true) {
20248
+ this.readySubject.next(true);
20226
20249
  // If subclasses implements OnReady
20227
20250
  if (typeof this['ngOnReady'] === 'function') {
20228
20251
  this.ngOnReady();
@@ -20234,18 +20257,18 @@
20234
20257
  * @param opts
20235
20258
  */
20236
20259
  AppForm.prototype.ready = function (opts) {
20237
- return waitForTrue(this._$ready, opts);
20260
+ if (this.readySubject.value)
20261
+ return Promise.resolve();
20262
+ return waitForTrue(this.readySubject, opts);
20238
20263
  };
20239
20264
  /**
20240
- * Wait form is idle (not loading)
20265
+ * Wait form is not busy (=loaded)
20241
20266
  * @param opts
20242
20267
  */
20243
20268
  AppForm.prototype.waitIdle = function (opts) {
20244
- return __awaiter(this, void 0, void 0, function () {
20245
- return __generator(this, function (_b) {
20246
- return [2 /*return*/, AppFormUtils.waitIdle(this, opts)];
20247
- });
20248
- });
20269
+ if (!this.loadingSubject.value)
20270
+ return Promise.resolve();
20271
+ return waitForFalse(this.loadingSubject, opts);
20249
20272
  };
20250
20273
  AppForm.prototype.updateValueAndValidity = function (opts) {
20251
20274
  AppFormUtils.updateValueAndValidity(this.form, opts);
@@ -20275,10 +20298,27 @@
20275
20298
  AppForm.prototype.registerAutocompleteField = function (fieldName, opts) {
20276
20299
  return this.autocompleteHelper.add(fieldName, opts);
20277
20300
  };
20301
+ AppForm.prototype.setError = function (value, opts) {
20302
+ if (this.errorSubject.value !== value) {
20303
+ this.errorSubject.next(value);
20304
+ if (!opts || opts.emitEvent !== false) {
20305
+ this.markForCheck();
20306
+ }
20307
+ }
20308
+ };
20278
20309
  AppForm.prototype.markForCheck = function () {
20279
20310
  // Should be overwritten by subclasses
20280
20311
  console.warn('markForCheck() has been called, but is not overwritten by component ' + this.constructor.name);
20281
20312
  };
20313
+ /* -- private function -- */
20314
+ AppForm.prototype.setLoading = function (value, opts) {
20315
+ if (this.loadingSubject.value !== value) {
20316
+ this.loadingSubject.next(value);
20317
+ if (!opts || opts.emitEvent !== false) {
20318
+ this.markForCheck();
20319
+ }
20320
+ }
20321
+ };
20282
20322
  return AppForm;
20283
20323
  }());
20284
20324
  AppForm.decorators = [
@@ -20739,14 +20779,14 @@
20739
20779
  }
20740
20780
  return this._onChange
20741
20781
  .pipe(operators.filter(isNotNil), operators.mergeMap(function (_) { return waitFor(function () { return !_this._saving; }); }), operators.mergeMap(function (_) { return __awaiter(_this, void 0, void 0, function () {
20742
- var excludedDataByFilter, excludedDataByPagination, data, promiseOrData, _a, total;
20743
- return __generator(this, function (_b) {
20744
- switch (_b.label) {
20782
+ var excludedDataByFilter, excludedDataByPagination, data, promiseOrData, _b, total;
20783
+ return __generator(this, function (_c) {
20784
+ switch (_c.label) {
20745
20785
  case 0:
20746
20786
  excludedDataByFilter = [];
20747
- _b.label = 1;
20787
+ _c.label = 1;
20748
20788
  case 1:
20749
- _b.trys.push([1, , 6, 7]);
20789
+ _c.trys.push([1, , 6, 7]);
20750
20790
  if (isEmptyArray(this.data)) {
20751
20791
  return [2 /*return*/, { data: [], total: 0 }];
20752
20792
  }
@@ -20756,14 +20796,14 @@
20756
20796
  if (!((promiseOrData instanceof Promise))) return [3 /*break*/, 3];
20757
20797
  return [4 /*yield*/, promiseOrData];
20758
20798
  case 2:
20759
- _a = _b.sent();
20799
+ _b = _c.sent();
20760
20800
  return [3 /*break*/, 4];
20761
20801
  case 3:
20762
- _a = promiseOrData;
20763
- _b.label = 4;
20802
+ _b = promiseOrData;
20803
+ _c.label = 4;
20764
20804
  case 4:
20765
- data = _a;
20766
- _b.label = 5;
20805
+ data = _b;
20806
+ _c.label = 5;
20767
20807
  case 5:
20768
20808
  // Apply filter (will update hiddenData)
20769
20809
  data = this.filter(data, filterData, excludedDataByFilter);
@@ -20819,16 +20859,16 @@
20819
20859
  };
20820
20860
  InMemoryEntitiesService.prototype.saveAll = function (data, options) {
20821
20861
  return __awaiter(this, void 0, void 0, function () {
20822
- var res, _a;
20823
- return __generator(this, function (_b) {
20824
- switch (_b.label) {
20862
+ var res, _b;
20863
+ return __generator(this, function (_c) {
20864
+ switch (_c.label) {
20825
20865
  case 0:
20826
20866
  if (!this.data)
20827
20867
  throw new Error('[memory-service] Could not save, because value not set');
20828
20868
  this.markAsSaving();
20829
- _b.label = 1;
20869
+ _c.label = 1;
20830
20870
  case 1:
20831
- _b.trys.push([1, , 6, 7]);
20871
+ _c.trys.push([1, , 6, 7]);
20832
20872
  // Restore hidden data
20833
20873
  if (isNotEmptyArray(this._hiddenData))
20834
20874
  data = data.concat.apply(data, __spread(this._hiddenData));
@@ -20837,14 +20877,14 @@
20837
20877
  if (!((res instanceof Promise))) return [3 /*break*/, 3];
20838
20878
  return [4 /*yield*/, res];
20839
20879
  case 2:
20840
- _a = _b.sent();
20880
+ _b = _c.sent();
20841
20881
  return [3 /*break*/, 4];
20842
20882
  case 3:
20843
- _a = res;
20844
- _b.label = 4;
20883
+ _b = res;
20884
+ _c.label = 4;
20845
20885
  case 4:
20846
- data = _a;
20847
- _b.label = 5;
20886
+ data = _b;
20887
+ _c.label = 5;
20848
20888
  case 5:
20849
20889
  this.data = data;
20850
20890
  this.dirty = true;
@@ -20861,7 +20901,7 @@
20861
20901
  return __awaiter(this, void 0, void 0, function () {
20862
20902
  var updatedData, deleteCount;
20863
20903
  var _this = this;
20864
- return __generator(this, function (_a) {
20904
+ return __generator(this, function (_b) {
20865
20905
  if (!this.data)
20866
20906
  throw new Error('[memory-service] Could not delete, because value not set');
20867
20907
  updatedData = this.data.filter(function (entity) {
@@ -20895,6 +20935,26 @@
20895
20935
  return this._equalsFn(d1, d2);
20896
20936
  return d1 && d1.equals ? d1.equals(d2) : EntityUtils.equals(d1, d2, 'id');
20897
20937
  };
20938
+ Object.defineProperty(InMemoryEntitiesService.prototype, "count", {
20939
+ /**
20940
+ * Count data stored by the service (without hidden data).
20941
+ * @param opts
20942
+ */
20943
+ get: function () {
20944
+ var _a;
20945
+ return (((_a = this.data) === null || _a === void 0 ? void 0 : _a.length) || 0);
20946
+ },
20947
+ enumerable: false,
20948
+ configurable: true
20949
+ });
20950
+ Object.defineProperty(InMemoryEntitiesService.prototype, "hiddenCount", {
20951
+ get: function () {
20952
+ var _a;
20953
+ return ((_a = this._hiddenData) === null || _a === void 0 ? void 0 : _a.length) || 0;
20954
+ },
20955
+ enumerable: false,
20956
+ configurable: true
20957
+ });
20898
20958
  /* -- protected methods -- */
20899
20959
  InMemoryEntitiesService.prototype.filter = function (data, _filter, hiddenData) {
20900
20960
  // if filter is DataFilter instance, use its test function
@@ -21522,7 +21582,12 @@
21522
21582
  }
21523
21583
  };
21524
21584
  AuthForm.prototype.cancel = function () {
21525
- this.onCancel.emit();
21585
+ return __awaiter(this, void 0, void 0, function () {
21586
+ return __generator(this, function (_a) {
21587
+ this.onCancel.emit();
21588
+ return [2 /*return*/];
21589
+ });
21590
+ });
21526
21591
  };
21527
21592
  AuthForm.prototype.doSubmit = function (event) {
21528
21593
  return __awaiter(this, void 0, void 0, function () {
@@ -22541,8 +22606,12 @@
22541
22606
  });
22542
22607
  return __awaiter(this, void 0, void 0, function () {
22543
22608
  return __generator(this, function (_c) {
22544
- _super.cancel.call(this);
22545
- return [2 /*return*/];
22609
+ switch (_c.label) {
22610
+ case 0: return [4 /*yield*/, _super.cancel.call(this)];
22611
+ case 1:
22612
+ _c.sent();
22613
+ return [2 /*return*/];
22614
+ }
22546
22615
  });
22547
22616
  });
22548
22617
  };
@@ -24749,7 +24818,7 @@
24749
24818
  MenuComponent.decorators = [
24750
24819
  { type: i0.Component, args: [{
24751
24820
  selector: 'app-menu',
24752
- template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n<!-- todo ajouter ici les 2 composants du module social -->\n\n </ion-row>\n </ion-grid>\n\n </ion-toolbar>\n\n <!-- User not logged -->\n <ng-template #notLogin>\n <mat-toolbar class=\"ion-padding\" @fadeInAnimation\n style=\"height: unset; display: block; margin: auto; text-align: center;\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"150px;\">\n <span *ngIf=\"!logo\" style=\"width: 150px\">{{appName}}</span>\n </mat-toolbar>\n </ng-template>\n </ion-header>\n\n <ion-content [class.has-user-header]=\"isLogin\">\n\n <ion-list lines=\"none\">\n <ion-menu-toggle auto-hide=\"false\"\n [class.flex-spacer]=\"item.cssClass == 'flex-spacer'\"\n *ngFor=\"let item of $items | async\">\n\n <!-- link -->\n <ion-item *ngIf=\"!loading && item.path\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n routerLinkActive=\"selected\"\n [routerLinkActiveOptions]=\"{exact: (item.path === '/')}\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- action -->\n <ion-item *ngIf=\"!loading && item.action\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n (click)=\"doAction(item.action, $event)\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- divider -->\n <ion-item-divider @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}}\"\n *ngIf=\"!loading && !item.path && !item.action\">\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item-divider>\n\n </ion-menu-toggle>\n </ion-list>\n </ion-content>\n\n <ion-footer class=\"hidden-xs hidden-sm\">\n <ion-toolbar>\n\n <ion-buttons slot=\"start\">\n <ion-button mat-icon-button color=\"accent\" (click)=\"openAboutModal($event)\">\n <mat-icon slot=\"icon-only\">help_outline</mat-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title (click)=\"openAboutModal($event)\" color=\"medium\">\n {{'MENU.FOOTER_VERSION_ABOUT'| translate: {version: appVersion} }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <button mat-icon-button color=\"accent\" (click)=\"toggleSplitPaneShow($event)\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(splitPane.when ? 'COMMON.BTN_HIDE_MENU' : 'COMMON.BTN_SHOW_MENU') |translate\">\n <mat-icon><span>{{splitPane.when ? '&#xab;' : '&#xbb;'}}</span></mat-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n\n </ion-menu>\n\n <ng-content></ng-content>\n\n</ion-split-pane>\n",
24821
+ template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n </ion-row>\n </ion-grid>\n\n </ion-toolbar>\n\n <!-- User not logged -->\n <ng-template #notLogin>\n <mat-toolbar class=\"ion-padding\" @fadeInAnimation\n style=\"height: unset; display: block; margin: auto; text-align: center;\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"150px;\">\n <span *ngIf=\"!logo\" style=\"width: 150px\">{{appName}}</span>\n </mat-toolbar>\n </ng-template>\n </ion-header>\n\n <ion-content [class.has-user-header]=\"isLogin\">\n\n <ion-list lines=\"none\">\n <ion-menu-toggle auto-hide=\"false\"\n [class.flex-spacer]=\"item.cssClass == 'flex-spacer'\"\n *ngFor=\"let item of $items | async\">\n\n <!-- link -->\n <ion-item *ngIf=\"!loading && item.path\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n routerLinkActive=\"selected\"\n [routerLinkActiveOptions]=\"{exact: (item.path === '/')}\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- action -->\n <ion-item *ngIf=\"!loading && item.action\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n (click)=\"doAction(item.action, $event)\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- divider -->\n <ion-item-divider @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}}\"\n *ngIf=\"!loading && !item.path && !item.action\">\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item-divider>\n\n </ion-menu-toggle>\n </ion-list>\n </ion-content>\n\n <ion-footer class=\"hidden-xs hidden-sm\">\n <ion-toolbar>\n\n <ion-buttons slot=\"start\">\n <ion-button mat-icon-button color=\"accent\" (click)=\"openAboutModal($event)\">\n <mat-icon slot=\"icon-only\">help_outline</mat-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title (click)=\"openAboutModal($event)\" color=\"medium\">\n {{'MENU.FOOTER_VERSION_ABOUT'| translate: {version: appVersion} }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <button mat-icon-button color=\"accent\" (click)=\"toggleSplitPaneShow($event)\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(splitPane.when ? 'COMMON.BTN_HIDE_MENU' : 'COMMON.BTN_SHOW_MENU') |translate\">\n <mat-icon><span>{{splitPane.when ? '&#xab;' : '&#xbb;'}}</span></mat-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n\n </ion-menu>\n\n <ng-content></ng-content>\n\n</ion-split-pane>\n",
24753
24822
  animations: [fadeInAnimation],
24754
24823
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
24755
24824
  styles: ["ion-menu{--ion-item-background:transparent;--ion-item-divider-background:transparent;--ion-item-icon-color:var(--ion-color-primary-tint);--ion-item-text-color:var(--ion-color-primary-tint);--ion-item-background-selected:var(--ion-color-secondary100);--ion-item-text-color-selected:var(--ion-color-primary);--ion-item-icon-color-selected:var(--ion-color-primary);--ion-item-text-color-disable:var(--ion-color-medium);--ion-item-icon-color-disable:var(--ion-color-medium)}ion-menu ion-header ion-text{color:var(--ion-color-primary)}ion-menu ion-header .user-avatar{background-size:cover;background-repeat:no-repeat;background-position:50%;background-color:var(--ion-color-secondary);border:1px solid var(--ion-color-primary);overflow:hidden!important;font-size:var(--avatar-size,60px)!important;line-height:var(--avatar-size,60px);height:var(--avatar-size,60px)!important;width:var(--avatar-size,60px)!important;border-radius:50%;display:inline-block}ion-menu ion-header .user-logo{text-align:right}ion-menu ion-header .user-logo img{max-width:120px;max-height:var(--avatar-size,60px);width:auto}ion-menu ion-header .username{padding-top:0;margin-top:0;margin-bottom:0;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-menu ion-header button[mat-button]{padding:0;text-align:start!important;width:100%}ion-menu .scroll-content{margin-top:79px!important}ion-menu .has-user-header .scroll-content{margin-top:188px!important}ion-menu ion-content.has-profile-header{--offset-top:188px}ion-menu ion-content.no-profile-header{--offset-top:79px}ion-menu ion-content ion-list{min-height:100%;display:flex;flex-direction:column;justify-content:flex-start}ion-menu ion-content ion-list ion-menu-toggle.flex-spacer{flex:1 1 auto;display:flex;flex-direction:column;justify-content:flex-end}ion-menu ion-content ion-list ion-item.primary{--ion-item-icon-color:var(--ion-color-primary-tint);--ion-item-text-color:var(--ion-color-primary-tint)}ion-menu ion-content ion-list ion-item.secondary{--ion-item-icon-color:var(--ion-color-secondary-tint);--ion-item-text-color:var(--ion-color-secondary-tint)}ion-menu ion-content ion-list ion-item.tertiary{--ion-item-icon-color:var(--ion-color-tertiary-tint);--ion-item-text-color:var(--ion-color-tertiary-tint)}ion-menu ion-content ion-list ion-item.danger{--ion-item-icon-color:var(--ion-color-danger-tint);--ion-item-text-color:var(--ion-color-danger-tint)}ion-menu ion-content ion-list ion-item.medium{--ion-item-icon-color:var(--ion-color-medium-shade);--ion-item-text-color:var(--ion-color-medium-shade)}ion-menu ion-content ion-list ion-item.dark{--ion-item-icon-color:var(--ion-color-dark-tint);--ion-item-text-color:var(--ion-color-dark-tint)}ion-menu ion-content ion-list ion-item ion-icon,ion-menu ion-content ion-list ion-item mat-icon{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-menu ion-content ion-list ion-item ion-label,ion-menu ion-content ion-list ion-item ion-text{color:var(--ion-item-text-color)!important}ion-menu ion-content ion-list ion-item.selected{background-color:var(--ion-item-background-selected)!important;--color-hover:var(--ion-item-background-selected)!important}ion-menu ion-content ion-list ion-item.selected ion-icon,ion-menu ion-content ion-list ion-item.selected mat-icon{color:var(--ion-item-icon-color-selected)!important;fill:currentColor;stroke:currentColor}ion-menu ion-content ion-list ion-item.selected ion-label,ion-menu ion-content ion-list ion-item.selected ion-text{color:var(--ion-item-text-color-selected)!important}ion-menu ion-content ion-list ion-item.selected:hover{--color-hover:var(--ion-item-background-selected)!important;--ion-item-icon-color-selected:var(--ion-item-icon-color)!important;--ion-item-text-color-selected:var(--ion-item-text-color)!important}ion-menu ion-footer{display:block!important}ion-menu ion-footer ion-toolbar ion-title{cursor:pointer;font-size:12pt;font-weight:400;text-align:center;padding:0 8px}ion-menu ion-footer ion-toolbar ion-button{--width:40px}@media screen and (max-width:767px){ion-menu ion-footer{display:none!important;visibility:hidden!important}}@media screen and (min-width:768px){ion-menu ion-scroll{overflow-y:auto!important}ion-menu .user-avatar{font-size:var(--avatar-size,80px)!important;line-height:var(--avatar-size,80px);height:var(--avatar-size,80px)!important;width:var(--avatar-size,80px)!important}ion-menu .user-logo img{max-height:var(--avatar-size,80px)}}"]
@@ -24817,7 +24886,6 @@
24817
24886
  this.icon = value.icon;
24818
24887
  this.matIcon = value.matIcon;
24819
24888
  this.matSvgIcon = value.matSvgIcon;
24820
- this.color = value.color;
24821
24889
  },
24822
24890
  enumerable: false,
24823
24891
  configurable: true
@@ -24828,7 +24896,7 @@
24828
24896
  AppIconComponent.decorators = [
24829
24897
  { type: i0.Component, args: [{
24830
24898
  selector: 'app-icon',
24831
- template: "<ion-icon *ngIf=\"icon; else matIconTemplate\" slot=\"icon-only\"\n [color]=\"color\"\n [name]=\"icon\"\n [style.height.px]=\"height\"\n [style.width.px]=\"width\"\n></ion-icon>\n<ng-template #matIconTemplate>\n <mat-icon [svgIcon]=\"matSvgIcon\"\n [style.color]=\"'var(--ion-color-'+color+')'\"\n [style.height.px]=\"height\"\n [style.width.px]=\"width\"\n [style.font-size.px]=\"height || width\"\n >{{matIcon}}</mat-icon>\n</ng-template>\n\n"
24899
+ template: "<ion-icon *ngIf=\"icon; else matIconTemplate\" slot=\"icon-only\"\n [color]=\"color\"\n [name]=\"icon\"\n></ion-icon>\n<ng-template #matIconTemplate>\n <mat-icon [svgIcon]=\"matSvgIcon\"\n [style.color]=\"'var(--ion-color-'+color+')'\">{{matIcon}}</mat-icon>\n</ng-template>\n\n"
24832
24900
  },] }
24833
24901
  ];
24834
24902
  AppIconComponent.propDecorators = {
@@ -24836,8 +24904,6 @@
24836
24904
  matIcon: [{ type: i0.Input }],
24837
24905
  matSvgIcon: [{ type: i0.Input }],
24838
24906
  color: [{ type: i0.Input }],
24839
- height: [{ type: i0.Input }],
24840
- width: [{ type: i0.Input }],
24841
24907
  ref: [{ type: i0.Input }]
24842
24908
  };
24843
24909
 
@@ -26074,10 +26140,6 @@
26074
26140
  get: function () {
26075
26141
  return this.errorSubject.value;
26076
26142
  },
26077
- /**
26078
- * @deprecated
26079
- * @param error
26080
- */
26081
26143
  set: function (error) {
26082
26144
  this.setError(error);
26083
26145
  },
@@ -26085,6 +26147,9 @@
26085
26147
  configurable: true
26086
26148
  });
26087
26149
  Object.defineProperty(AppTable.prototype, "error$", {
26150
+ /**
26151
+ * @deprecated
26152
+ */
26088
26153
  get: function () {
26089
26154
  return this.errorSubject.asObservable();
26090
26155
  },
@@ -26603,7 +26668,7 @@
26603
26668
  .then(function () { return _this.editRowById(event, row.id, { focusColumn: _this.lastUserColumn }); });
26604
26669
  return true;
26605
26670
  }
26606
- // Edit next row
26671
+ // Edit previous row
26607
26672
  this.editRow(event, row, { focusColumn: this.lastUserColumn });
26608
26673
  return true;
26609
26674
  };
@@ -26631,8 +26696,7 @@
26631
26696
  if (id < 0)
26632
26697
  return [2 /*return*/];
26633
26698
  if (!(id >= this.visibleRowCount)) return [3 /*break*/, 1];
26634
- this.focusColumn = opts && opts.focusColumn || this.firstUserColumn;
26635
- this.addRow(event);
26699
+ this.addRow(event, undefined, opts);
26636
26700
  return [3 /*break*/, 3];
26637
26701
  case 1: return [4 /*yield*/, this.dataSource.getRow(id)];
26638
26702
  case 2:
@@ -26710,7 +26774,7 @@
26710
26774
  this.cancelExistingRow(event, row, opts);
26711
26775
  }
26712
26776
  };
26713
- AppTable.prototype.addRow = function (event, insertAt) {
26777
+ AppTable.prototype.addRow = function (event, insertAt, opts) {
26714
26778
  if (this.debug)
26715
26779
  console.debug('[table] Asking for new row...');
26716
26780
  if (!this._enabled)
@@ -26725,7 +26789,7 @@
26725
26789
  return false;
26726
26790
  }
26727
26791
  // Add new row
26728
- this.addRowToTable(insertAt);
26792
+ this.addRowToTable(insertAt, opts);
26729
26793
  return true;
26730
26794
  };
26731
26795
  AppTable.prototype.save = function (opts) {
@@ -26870,7 +26934,7 @@
26870
26934
  * @param event
26871
26935
  * @param row
26872
26936
  * @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
26873
- * Use skipIfLoading=false to force deletion even if table is busy
26937
+ * And to force deletion even if table is busy
26874
26938
  */
26875
26939
  AppTable.prototype.deleteRow = function (event, row, opts) {
26876
26940
  return __awaiter(this, void 0, void 0, function () {
@@ -26890,7 +26954,7 @@
26890
26954
  * @param event
26891
26955
  * @param rows
26892
26956
  * @param opts Use interactive=false to avoid user interaction (e.g. user confirmation)
26893
- * Use skipIfLoading=false to force deletion even if table is busy
26957
+ * And to force deletion even if table is busy
26894
26958
  */
26895
26959
  AppTable.prototype.deleteRows = function (event, rows, opts) {
26896
26960
  var _a;
@@ -26908,8 +26972,8 @@
26908
26972
  event === null || event === void 0 ? void 0 : event.preventDefault();
26909
26973
  if (!this._enabled || isEmptyArray(rows))
26910
26974
  return [2 /*return*/, 0]; // Skip is disabled, or no rows to delete
26911
- if (this.loading && (!opts || opts.skipIfLoading !== false)) {
26912
- console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.skipLoading = false to force deletion');
26975
+ if (this.loading && (!opts || opts.interactive !== false)) {
26976
+ console.warn('[app-table] Skip deleteRows() because table is busy (loading). Use opts.interactive = false to force deletion');
26913
26977
  return [2 /*return*/, 0]; // Skip if loading
26914
26978
  }
26915
26979
  // Make sure to keep newly created row
@@ -27068,29 +27132,11 @@
27068
27132
  AppTable.prototype.moveRow = function (id, direction) {
27069
27133
  this.dataSource.move(id, direction);
27070
27134
  };
27071
- AppTable.prototype.ready = function () {
27072
- return __awaiter(this, void 0, void 0, function () {
27073
- return __generator(this, function (_e) {
27074
- switch (_e.label) {
27075
- case 0: return [4 /*yield*/, firstTruePromise(this.readySubject)];
27076
- case 1:
27077
- _e.sent();
27078
- return [2 /*return*/];
27079
- }
27080
- });
27081
- });
27135
+ AppTable.prototype.ready = function (opts) {
27136
+ return waitForTrue(this.readySubject, opts);
27082
27137
  };
27083
27138
  AppTable.prototype.waitIdle = function (opts) {
27084
- return __awaiter(this, void 0, void 0, function () {
27085
- return __generator(this, function (_e) {
27086
- switch (_e.label) {
27087
- case 0: return [4 /*yield*/, firstFalsePromise(this.loadingSubject)];
27088
- case 1:
27089
- _e.sent();
27090
- return [2 /*return*/];
27091
- }
27092
- });
27093
- });
27139
+ return waitForFalse(this.loadingSubject, opts);
27094
27140
  };
27095
27141
  AppTable.prototype.openSelectColumnsModal = function (event) {
27096
27142
  return __awaiter(this, void 0, void 0, function () {
@@ -27548,12 +27594,13 @@
27548
27594
  //if (this.debug) console.debug("[table] id = " + id);
27549
27595
  return id;
27550
27596
  };
27551
- AppTable.prototype.addRowToTable = function (insertAt) {
27597
+ AppTable.prototype.addRowToTable = function (insertAt, opts) {
27552
27598
  return __awaiter(this, void 0, void 0, function () {
27553
27599
  return __generator(this, function (_e) {
27554
27600
  switch (_e.label) {
27555
27601
  case 0:
27556
27602
  this.focusFirstColumn = true;
27603
+ this.focusColumn = (opts === null || opts === void 0 ? void 0 : opts.focusColumn) || this.firstUserColumn;
27557
27604
  return [4 /*yield*/, this._dataSource.asyncCreateNew(insertAt)];
27558
27605
  case 1:
27559
27606
  _e.sent();
@@ -27934,8 +27981,9 @@
27934
27981
  this._subscription = new rxjs.Subscription();
27935
27982
  this._enabled = false;
27936
27983
  this._dirty = false;
27937
- this._$ready = new rxjs.BehaviorSubject(false);
27938
- this._$loading = new rxjs.BehaviorSubject(true);
27984
+ this.readySubject = new rxjs.BehaviorSubject(false);
27985
+ this.loadingSubject = new rxjs.BehaviorSubject(true);
27986
+ this.errorSubject = new rxjs.BehaviorSubject(undefined);
27939
27987
  this.debug = false;
27940
27988
  this.submitted = false;
27941
27989
  this.toolbar = null;
@@ -27946,13 +27994,43 @@
27946
27994
  * @deprecated
27947
27995
  */
27948
27996
  get: function () {
27949
- return this._$loading.value;
27997
+ return this.loadingSubject.value;
27950
27998
  },
27951
27999
  /**
27952
28000
  * @deprecated
27953
28001
  */
27954
28002
  set: function (value) {
27955
- this._$loading.next(value);
28003
+ this.readySubject.next(value);
28004
+ },
28005
+ enumerable: false,
28006
+ configurable: true
28007
+ });
28008
+ Object.defineProperty(AppEditor.prototype, "_$ready", {
28009
+ /**
28010
+ * @deprecated
28011
+ */
28012
+ get: function () {
28013
+ return this.readySubject;
28014
+ },
28015
+ enumerable: false,
28016
+ configurable: true
28017
+ });
28018
+ Object.defineProperty(AppEditor.prototype, "_$loading", {
28019
+ /**
28020
+ * @deprecated
28021
+ */
28022
+ get: function () {
28023
+ return this.loadingSubject;
28024
+ },
28025
+ enumerable: false,
28026
+ configurable: true
28027
+ });
28028
+ Object.defineProperty(AppEditor.prototype, "error", {
28029
+ get: function () {
28030
+ return this.errorSubject.value;
28031
+ },
28032
+ set: function (error) {
28033
+ this.setError(error);
27956
28034
  },
27957
28035
  enumerable: false,
27958
28036
  configurable: true
@@ -28009,7 +28087,7 @@
28009
28087
  Object.defineProperty(AppEditor.prototype, "loading", {
28010
28088
  get: function () {
28011
28089
  var _a;
28012
- return this._$loading.value || (((_a = this._children) === null || _a === void 0 ? void 0 : _a.findIndex(function (c) { return c.enabled && c.loading; })) !== -1) || false;
28090
+ return this.loadingSubject.value || (((_a = this._children) === null || _a === void 0 ? void 0 : _a.findIndex(function (c) { return c.enabled && c.loading; })) !== -1) || false;
28013
28091
  },
28014
28092
  enumerable: false,
28015
28093
  configurable: true
@@ -28053,10 +28131,9 @@
28053
28131
  };
28054
28132
  AppEditor.prototype.ngOnDestroy = function () {
28055
28133
  this._subscription.unsubscribe();
28056
- this._$ready.complete();
28057
- this._$ready.unsubscribe();
28058
- this._$loading.complete();
28059
- this._$loading.unsubscribe();
28134
+ this.readySubject.unsubscribe();
28135
+ this.loadingSubject.unsubscribe();
28136
+ this.errorSubject.unsubscribe();
28060
28137
  };
28061
28138
  AppEditor.prototype.addChildForm = function (form) {
28062
28139
  if (!form)
@@ -28126,16 +28203,16 @@
28126
28203
  this.markForCheck();
28127
28204
  };
28128
28205
  AppEditor.prototype.markAsLoading = function (opts) {
28129
- if (!this._loading) {
28130
- this._loading = true;
28206
+ if (!this.loadingSubject.value) {
28207
+ this.loadingSubject.next(true);
28131
28208
  if (!opts || opts.emitEvent !== false)
28132
28209
  this.markForCheck();
28133
28210
  }
28134
28211
  };
28135
28212
  AppEditor.prototype.markAsLoaded = function (opts) {
28136
28213
  var _a;
28137
- if (this._loading) {
28138
- this._loading = false;
28214
+ if (this.loadingSubject.value) {
28215
+ this.loadingSubject.next(false);
28139
28216
  if (!opts || opts.onlySelf !== true) {
28140
28217
  // Emit to children forms
28141
28218
  // Tables should be changed by parent
@@ -28149,17 +28226,17 @@
28149
28226
  AppEditor.prototype.markAsReady = function (opts) {
28150
28227
  var _a;
28151
28228
  (_a = this._children) === null || _a === void 0 ? void 0 : _a.forEach(function (c) { return c.markAsReady(opts); });
28152
- this._$ready.next(true);
28229
+ this.readySubject.next(true);
28153
28230
  };
28154
28231
  AppEditor.prototype.ready = function (opts) {
28155
- return __awaiter(this, void 0, void 0, function () {
28156
- return __generator(this, function (_b) {
28157
- return [2 /*return*/, waitForTrue(this._$ready, opts)];
28158
- });
28159
- });
28232
+ if (this.readySubject.value)
28233
+ return Promise.resolve();
28234
+ return waitForTrue(this.readySubject, opts);
28160
28235
  };
28161
28236
  AppEditor.prototype.waitIdle = function (opts) {
28162
- return AppFormUtils.waitIdle(this, opts);
28237
+ if (!this.loadingSubject.value)
28238
+ return Promise.resolve();
28239
+ return waitForFalse(this.loadingSubject, opts);
28163
28240
  };
28164
28241
  AppEditor.prototype.cancel = function (event) {
28165
28242
  return __awaiter(this, void 0, void 0, function () {
@@ -28415,6 +28492,14 @@
28415
28492
  console.warn(prefix + " Unknown children sub-form: ", c);
28416
28493
  }
28417
28494
  };
28495
+ AppEditor.prototype.setError = function (value, opts) {
28496
+ if (this.errorSubject.value !== value) {
28497
+ this.errorSubject.next(value);
28498
+ if (!opts || opts.emitEvent !== false) {
28499
+ this.markForCheck();
28500
+ }
28501
+ }
28502
+ };
28418
28503
  AppEditor.prototype.markForCheck = function () {
28419
28504
  // Should be override by subclasses, if change detection is Push
28420
28505
  };
@@ -28510,6 +28595,10 @@
28510
28595
  this.markForCheck();
28511
28596
  }
28512
28597
  };
28598
+ AppTabEditor.prototype.realignInkBar = function () {
28599
+ var _a;
28600
+ (_a = this.tabGroup) === null || _a === void 0 ? void 0 : _a.realignInkBar();
28601
+ };
28513
28602
  AppTabEditor.prototype.onTabChange = function (event, queryTabIndexParamName) {
28514
28603
  queryTabIndexParamName = queryTabIndexParamName || this.queryTabIndexParamName;
28515
28604
  if (!queryTabIndexParamName || !this.route)
@@ -29757,18 +29846,22 @@
29757
29846
  console.debug(this._logPrefix + 'Saving data...');
29758
29847
  _c.label = 2;
29759
29848
  case 2:
29760
- _c.trys.push([2, 4, 5, 6]);
29761
- saved = Promise.all((this.tables || [])
29762
- .filter(function (c) { return c.dirty; })
29763
- .map(function (c) { return c.save(); }))
29764
- .then(function (res) { return res.findIndex(function (r) { return r !== true; }) === -1; });
29849
+ _c.trys.push([2, 5, 6, 7]);
29850
+ return [4 /*yield*/, this.saveDirtyTables()];
29851
+ case 3:
29852
+ saved = _c.sent();
29853
+ if (!saved)
29854
+ return [2 /*return*/, false];
29855
+ // Fill data
29765
29856
  _b = this;
29766
29857
  return [4 /*yield*/, this.getValue()];
29767
- case 3:
29858
+ case 4:
29859
+ // Fill data
29768
29860
  _b.data = _c.sent();
29861
+ // Mark as submitted
29769
29862
  this.submitted = true;
29770
- return [2 /*return*/, saved];
29771
- case 4:
29863
+ return [2 /*return*/, true];
29864
+ case 5:
29772
29865
  err_2 = _c.sent();
29773
29866
  this.submitted = true;
29774
29867
  this.setError(err_2);
@@ -29777,10 +29870,10 @@
29777
29870
  this.markAsDirty();
29778
29871
  this.enable();
29779
29872
  return [2 /*return*/, false];
29780
- case 5:
29873
+ case 6:
29781
29874
  this.markAsSaved();
29782
29875
  return [7 /*endfinally*/];
29783
- case 6: return [2 /*return*/];
29876
+ case 7: return [2 /*return*/];
29784
29877
  }
29785
29878
  });
29786
29879
  });
@@ -29904,6 +29997,22 @@
29904
29997
  this.markForCheck();
29905
29998
  };
29906
29999
  /* -- protected methods -- */
30000
+ AppEntityEditorModal.prototype.saveDirtyTables = function () {
30001
+ return __awaiter(this, void 0, void 0, function () {
30002
+ var results, saved;
30003
+ return __generator(this, function (_b) {
30004
+ switch (_b.label) {
30005
+ case 0: return [4 /*yield*/, Promise.all((this.tables || [])
30006
+ .filter(function (c) { return c.dirty; })
30007
+ .map(function (c) { return c.save(); }))];
30008
+ case 1:
30009
+ results = _b.sent();
30010
+ saved = results.findIndex(function (result) { return result !== true; }) === -1;
30011
+ return [2 /*return*/, saved];
30012
+ }
30013
+ });
30014
+ });
30015
+ };
29907
30016
  AppEntityEditorModal.prototype.waitWhilePending = function (opts) {
29908
30017
  return AppFormUtils.waitWhilePending(this, opts);
29909
30018
  };
@@ -30056,10 +30165,7 @@
30056
30165
  var SocialErrorCodes = {
30057
30166
  LOAD_USER_EVENTS_ERROR: 50000,
30058
30167
  SAVE_USER_EVENT_ERROR: 50001,
30059
- COUNT_USER_EVENT_ERROR: 50002,
30060
- SEND_MESSAGE_ERROR: 50003,
30061
- SUBSCRIBE_USER_EVENTS_ERROR: 50005,
30062
- SUBSCRIBE_JOB_PROGRESSION_ERROR: 50010
30168
+ SEND_MESSAGE_ERROR: 50003
30063
30169
  };
30064
30170
 
30065
30171
  var UserEvent_1;
@@ -30075,23 +30181,16 @@
30075
30181
  }
30076
30182
  UserEvent.prototype.asObject = function (opts) {
30077
30183
  var target = _super.prototype.asObject.call(this, opts);
30078
- target.creationDate = toDateISOString(this.creationDate);
30079
- target.readDate = toDateISOString(this.readDate);
30080
30184
  // Serialize content
30081
30185
  if (typeof target.content === 'object') {
30082
30186
  target.content = JSON.stringify(target.content);
30083
30187
  }
30084
- delete target.avatar;
30085
- delete target.avatarIcon;
30086
- delete target.icon;
30087
- delete target.actions;
30088
30188
  return target;
30089
30189
  };
30090
30190
  UserEvent.prototype.fromObject = function (source) {
30091
30191
  Object.assign(this, source); // Copy all properties
30092
30192
  _super.prototype.fromObject.call(this, source);
30093
30193
  this.creationDate = fromDateISOString(source.creationDate);
30094
- this.readDate = fromDateISOString(source.readDate);
30095
30194
  try {
30096
30195
  // Deserialize content
30097
30196
  if (typeof source.content === 'string' && source.content.startsWith('{')) {
@@ -30111,48 +30210,36 @@
30111
30210
  exports.UserEvent = UserEvent_1 = __decorate([
30112
30211
  EntityClass({ typename: 'UserEventVO' })
30113
30212
  ], exports.UserEvent);
30213
+
30214
+ var UserEventFragments = {
30215
+ userEvent: core.gql(templateObject_1$2 || (templateObject_1$2 = __makeTemplateObject(["fragment UserEventFragment on UserEventVO {\n id\n issuer\n updateDate\n creationDate\n eventType\n recipient\n content\n hash\n signature\n readSignature\n __typename\n }"], ["fragment UserEventFragment on UserEventVO {\n id\n issuer\n updateDate\n creationDate\n eventType\n recipient\n content\n hash\n signature\n readSignature\n __typename\n }"]))),
30216
+ lightUserEvent: core.gql(templateObject_2$2 || (templateObject_2$2 = __makeTemplateObject(["fragment LightUserEventFragment on UserEventVO {\n id\n issuer\n recipient\n updateDate\n creationDate\n eventType\n readSignature\n __typename\n }"], ["fragment LightUserEventFragment on UserEventVO {\n id\n issuer\n recipient\n updateDate\n creationDate\n eventType\n readSignature\n __typename\n }"])))
30217
+ };
30218
+ var templateObject_1$2, templateObject_2$2;
30219
+
30114
30220
  // @dynamic
30115
30221
  exports.UserEventFilter = /** @class */ (function (_super) {
30116
30222
  __extends(UserEventFilter, _super);
30117
30223
  function UserEventFilter() {
30118
30224
  var _this = _super.apply(this, __spread(arguments)) || this;
30119
- _this.types = [];
30120
- _this.levels = [];
30121
- _this.issuers = [];
30122
- _this.recipients = [];
30123
- _this.startDate = null;
30124
- _this.excludeRead = false;
30225
+ _this.issuer = null;
30226
+ _this.recipient = null;
30125
30227
  return _this;
30126
30228
  }
30127
30229
  UserEventFilter.prototype.fromObject = function (source, opts) {
30128
30230
  _super.prototype.fromObject.call(this, source, opts);
30129
- this.types = source.types || [];
30130
- this.levels = source.levels || [];
30131
- this.issuers = source.issuers || [];
30132
- this.recipients = source.recipients || [];
30133
- this.startDate = fromDateISOString(source.startDate);
30134
- this.excludeRead = source.excludeRead || false;
30231
+ this.issuer = source.issuer;
30232
+ this.recipient = source.recipient;
30135
30233
  };
30136
30234
  UserEventFilter.prototype.buildFilter = function () {
30137
30235
  var _this = this;
30138
30236
  var filterFns = _super.prototype.buildFilter.call(this);
30139
- if (isNotEmptyArray(this.types)) {
30140
- filterFns.push(function (t) { return _this.types.includes(t.type); });
30141
- }
30142
- if (isNotEmptyArray(this.levels)) {
30143
- filterFns.push(function (t) { return _this.levels.includes(t.level); });
30144
- }
30145
- if (isNotEmptyArray(this.issuers)) {
30146
- filterFns.push(function (t) { return _this.issuers.includes(t.issuer); });
30237
+ // issuer
30238
+ if (this.issuer) {
30239
+ filterFns.push(function (t) { return (t.issuer === _this.issuer); });
30147
30240
  }
30148
- if (isNotEmptyArray(this.recipients)) {
30149
- filterFns.push(function (t) { return _this.recipients.includes(t.recipient); });
30150
- }
30151
- if (isNotNil(this.startDate)) {
30152
- filterFns.push(function (t) { return _this.startDate.isSameOrBefore(t.creationDate); });
30153
- }
30154
- if (this.excludeRead === true) {
30155
- filterFns.push(function (t) { return isNil(t.readSignature); }); // todo or t.signature ?
30241
+ if (this.recipient) {
30242
+ filterFns.push(function (t) { return (t.recipient === _this.recipient); });
30156
30243
  }
30157
30244
  return filterFns;
30158
30245
  };
@@ -30161,273 +30248,120 @@
30161
30248
  exports.UserEventFilter = __decorate([
30162
30249
  EntityClass({ typename: 'UserEventFilterVO' })
30163
30250
  ], exports.UserEventFilter);
30164
-
30165
- var UserEventFragments = {
30166
- userEvent: core.gql(templateObject_1$2 || (templateObject_1$2 = __makeTemplateObject(["fragment UserEventFragment on UserEventVO {\n id\n issuer\n updateDate\n creationDate\n eventType\n recipient\n content\n hash\n signature\n readSignature\n __typename\n }"], ["fragment UserEventFragment on UserEventVO {\n id\n issuer\n updateDate\n creationDate\n eventType\n recipient\n content\n hash\n signature\n readSignature\n __typename\n }"]))),
30167
- lightUserEvent: core.gql(templateObject_2$2 || (templateObject_2$2 = __makeTemplateObject(["fragment LightUserEventFragment on UserEventVO {\n id\n issuer\n recipient\n updateDate\n creationDate\n eventType\n readSignature\n __typename\n }"], ["fragment LightUserEventFragment on UserEventVO {\n id\n issuer\n recipient\n updateDate\n creationDate\n eventType\n readSignature\n __typename\n }"])))
30168
- };
30169
- var templateObject_1$2, templateObject_2$2;
30170
-
30171
- var moment$6 = momentImported__namespace;
30172
- var UserEventServiceToken = new i0.InjectionToken('UserEventService');
30173
- var AbstractUserEventService = /** @class */ (function (_super) {
30174
- __extends(AbstractUserEventService, _super);
30175
- function AbstractUserEventService(graphql, accountService, network, translate, queries, mutations, subscriptions, environment) {
30251
+ var SaveQuery = core.gql(templateObject_1$3 || (templateObject_1$3 = __makeTemplateObject(["\n mutation SaveUserEvent($data: UserEventVOInput){\n data: saveUserEvent(userEvent: $data){\n ...UserEventFragment\n }\n }\n ", "\n"], ["\n mutation SaveUserEvent($data: UserEventVOInput){\n data: saveUserEvent(userEvent: $data){\n ...UserEventFragment\n }\n }\n ", "\n"])), UserEventFragments.userEvent);
30252
+ var LoadAllQuery = core.gql(templateObject_2$3 || (templateObject_2$3 = __makeTemplateObject(["\n query UserEvents($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...LightUserEventFragment\n }\n }\n ", "\n"], ["\n query UserEvents($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...LightUserEventFragment\n }\n }\n ", "\n"])), UserEventFragments.lightUserEvent);
30253
+ var DeleteByIdsMutation = core.gql(templateObject_3$2 || (templateObject_3$2 = __makeTemplateObject(["\n mutation DeleteUserEvents($ids:[Int]){\n deleteUserEvents(ids: $ids)\n }\n"], ["\n mutation DeleteUserEvents($ids:[Int]){\n deleteUserEvents(ids: $ids)\n }\n"])));
30254
+ var LoadAllWithContentQuery = core.gql(templateObject_4$2 || (templateObject_4$2 = __makeTemplateObject(["\n query UserEventsWithContent($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...UserEventFragment\n }\n }\n ", "\n"], ["\n query UserEventsWithContent($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...UserEventFragment\n }\n }\n ", "\n"])), UserEventFragments.userEvent);
30255
+ var UserEventService = /** @class */ (function (_super) {
30256
+ __extends(UserEventService, _super);
30257
+ function UserEventService(graphql, accountService, network, translate, toastController, environment) {
30176
30258
  var _this = _super.call(this, graphql, environment) || this;
30177
30259
  _this.graphql = graphql;
30178
30260
  _this.accountService = accountService;
30179
30261
  _this.network = network;
30180
30262
  _this.translate = translate;
30181
- _this.queries = queries;
30182
- _this.mutations = mutations;
30183
- _this.subscriptions = subscriptions;
30263
+ _this.toastController = toastController;
30184
30264
  _this.environment = environment;
30185
- _this._count$ = new rxjs.BehaviorSubject(0);
30186
- _this._subscriptions = new rxjs.Subscription();
30187
- _this.listeners = [];
30188
- _this._logPrefix = '[user-event-service] ';
30265
+ _this._userEventActions = [];
30189
30266
  // For DEV only
30190
- _this._debug = !(environment === null || environment === void 0 ? void 0 : environment.production);
30191
- // listen login/logout
30192
- _this._subscriptions.add(accountService.onLogin.subscribe(function () { return __awaiter(_this, void 0, void 0, function () {
30193
- var count;
30194
- return __generator(this, function (_b) {
30195
- switch (_b.label) {
30196
- case 0: return [4 /*yield*/, this.count(this.defaultFilter())];
30197
- case 1:
30198
- count = _b.sent();
30199
- if (count && this._debug) {
30200
- console.debug(this._logPrefix + "Received " + count + " unread notifications");
30201
- }
30202
- this._count$.next(count);
30203
- return [2 /*return*/];
30204
- }
30205
- });
30206
- }); }));
30267
+ _this._debug = environment && !environment.production;
30207
30268
  return _this;
30208
30269
  }
30209
- Object.defineProperty(AbstractUserEventService.prototype, "userEventCount", {
30210
- get: function () {
30211
- return this._count$.asObservable();
30212
- },
30213
- enumerable: false,
30214
- configurable: true
30215
- });
30216
- AbstractUserEventService.prototype.ngOnDestroy = function () {
30217
- this._subscriptions.unsubscribe();
30218
- };
30219
- AbstractUserEventService.prototype.watchAll = function (offset, size, sortBy, sortDirection, filter, options) {
30270
+ /**
30271
+ *
30272
+ * @param offset
30273
+ * @param size
30274
+ * @param sortBy
30275
+ * @param sortDirection
30276
+ * @param filter
30277
+ * @param options
30278
+ * @deprecated use watchPage() instead
30279
+ */
30280
+ UserEventService.prototype.watchAll = function (offset, size, sortBy, sortDirection, filter, options) {
30220
30281
  return this.watchPage({ offset: offset, size: size, sortBy: sortBy, sortDirection: sortDirection }, filter, options);
30221
30282
  };
30222
- AbstractUserEventService.prototype.watchPage = function (page, filter, options) {
30223
- var _this = this;
30224
- var _a;
30283
+ UserEventService.prototype.watchPage = function (page, filter, options) {
30225
30284
  var now = this._debug && Date.now();
30226
30285
  //if (this._debug)
30227
- console.debug(this._logPrefix + "Loading user events...", filter);
30286
+ console.debug('[user-event-service] Loading user events...', filter);
30228
30287
  filter = this.asFilter(filter);
30229
30288
  // Force recipient to current issuer, if not admin and not specified
30230
- if (isEmptyArray(filter === null || filter === void 0 ? void 0 : filter.recipients) || !this.accountService.isAdmin()) {
30231
- var recipient = this.defaultRecipient();
30232
- if (!((_a = filter === null || filter === void 0 ? void 0 : filter.recipients) === null || _a === void 0 ? void 0 : _a.includes(recipient))) {
30289
+ if (isNilOrBlank(filter.recipient) || !this.accountService.isAdmin()) {
30290
+ var recipient = this.accountService.account.pubkey;
30291
+ if (recipient !== filter.recipient) {
30233
30292
  console.warn('[user-events-service] Force user event filter.recipient=' + recipient);
30234
- filter.recipients = [recipient];
30293
+ filter.recipient = recipient;
30235
30294
  }
30236
30295
  }
30237
- var withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
30296
+ var withContent = options && options.withContent === true;
30238
30297
  return this.mutableWatchQuery({
30239
30298
  queryName: withContent ? 'LoadAllWithContent' : 'LoadAll',
30240
- query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
30299
+ query: withContent ? LoadAllWithContentQuery : LoadAllQuery,
30241
30300
  variables: {
30242
- page: Object.assign({ sortBy: 'updateDate', sortDirection: 'desc' }, page),
30301
+ page: Object.assign(Object.assign({ sortBy: 'updateDate' }, page), { sortDirection: (page.sortDirection || 'DESC').toUpperCase() }),
30243
30302
  filter: filter && filter.asPodObject()
30244
30303
  },
30245
30304
  arrayFieldName: 'data',
30246
30305
  error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
30247
- fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || "cache-first"
30306
+ fetchPolicy: options && options.fetchPolicy || undefined
30248
30307
  })
30249
30308
  .pipe(operators.map(function (res) {
30250
- var data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(_this.processUserEvent);
30309
+ var data = res && (res.data || []).map(exports.UserEvent.fromObject);
30251
30310
  if (now) {
30252
- console.debug("" + _this._logPrefix + data.length + " user events loaded in " + (Date.now() - now) + "ms");
30311
+ console.debug("[user-event-service] " + data.length + " user events loaded in " + (Date.now() - now) + "ms");
30253
30312
  now = null;
30254
30313
  }
30255
- var unreadCount = _this.unreadEvents(data);
30256
30314
  return {
30257
30315
  data: data,
30258
- total: toNumber(res === null || res === void 0 ? void 0 : res.total, unreadCount)
30316
+ total: res && toNumber(res.total, data.length)
30259
30317
  };
30260
30318
  }));
30261
30319
  };
30262
- AbstractUserEventService.prototype.add = function (entity) {
30263
- // TODO set an id !!!!!!!!!!!!!!!!!!!!!!!!!
30264
- entity = this.processUserEvent(entity);
30265
- var withContent = !!entity.content;
30266
- // Add user event locally
30267
- this.insertIntoMutableCachedQueries(this.graphql.cache, {
30268
- query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
30269
- data: entity
30270
- });
30271
- // Update count
30272
- this._count$.next(this._count$.value + 1);
30273
- };
30274
- AbstractUserEventService.prototype.count = function (filter, options) {
30275
- var _a;
30276
- return __awaiter(this, void 0, void 0, function () {
30277
- var res;
30278
- return __generator(this, function (_b) {
30279
- switch (_b.label) {
30280
- case 0:
30281
- if (!((_a = this.queries) === null || _a === void 0 ? void 0 : _a.count)) {
30282
- console.warn(this._logPrefix + "Query 'count' not provided, skip.");
30283
- return [2 /*return*/, undefined];
30284
- }
30285
- if (!filter)
30286
- throw new Error("Missing argument 'filter'");
30287
- filter = this.asFilter(filter);
30288
- if (this._debug)
30289
- console.debug(this._logPrefix + "Counting user events with filter:", filter);
30290
- return [4 /*yield*/, this.graphql.query({
30291
- query: this.queries.count,
30292
- variables: {
30293
- filter: filter.asPodObject()
30294
- },
30295
- error: { code: SocialErrorCodes.COUNT_USER_EVENT_ERROR, message: 'SOCIAL.ERROR.COUNT_USER_EVENT_ERROR' },
30296
- fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || 'network-only'
30297
- })];
30298
- case 1:
30299
- res = _b.sent();
30300
- return [2 /*return*/, res.total];
30301
- }
30302
- });
30303
- });
30304
- };
30305
- AbstractUserEventService.prototype.listenChanges = function (filter, options) {
30320
+ UserEventService.prototype.saveAll = function (data, options) {
30306
30321
  var _this = this;
30307
- var _a;
30308
- if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenChanges)) {
30309
- console.warn(this._logPrefix + "Subscription query 'listenChanges' not provided, skip.");
30310
- return rxjs.of();
30311
- }
30312
- if (!filter)
30313
- throw new Error("Missing argument 'filter'");
30314
- filter = this.asFilter(filter);
30315
- var withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
30316
- if (this._debug)
30317
- console.debug(this._logPrefix + "[WS] Listening changes for user events with filter:", filter);
30318
- return this.graphql.subscribe({
30319
- query: this.subscriptions.listenChanges,
30320
- fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
30321
- variables: { filter: filter.asPodObject(), interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
30322
- error: {
30323
- code: SocialErrorCodes.SUBSCRIBE_USER_EVENTS_ERROR,
30324
- message: 'SOCIAL.ERROR.SUBSCRIBE_USER_EVENTS_ERROR'
30325
- }
30326
- }).pipe(operators.map(function (_b) {
30327
- var data = _b.data;
30328
- if (data && _this._debug)
30329
- console.debug(_this._logPrefix + "Received new user events:", data);
30330
- var updatedData = data === null || data === void 0 ? void 0 : data.map(_this.processUserEvent);
30331
- // Update cache
30332
- _this.insertIntoMutableCachedQueries(_this.graphql.cache, {
30333
- query: withContent ? _this.queries.loadAllWithContent : _this.queries.loadAll,
30334
- data: updatedData
30335
- });
30336
- // update count
30337
- _this._count$.next(_this.unreadEvents(updatedData));
30338
- return updatedData;
30339
- }));
30340
- };
30341
- AbstractUserEventService.prototype.delete = function (entity) {
30342
- return __awaiter(this, void 0, void 0, function () {
30343
- return __generator(this, function (_b) {
30344
- switch (_b.label) {
30345
- case 0:
30346
- if (!entity)
30347
- return [2 /*return*/]; // skip
30348
- return [4 /*yield*/, this.deleteAll([entity])];
30349
- case 1:
30350
- _b.sent();
30351
- return [2 /*return*/];
30352
- }
30353
- });
30354
- });
30355
- };
30356
- AbstractUserEventService.prototype.deleteAll = function (entities, opts) {
30357
- return __awaiter(this, void 0, void 0, function () {
30358
- var ids, now;
30359
- var _this = this;
30360
- return __generator(this, function (_b) {
30361
- switch (_b.label) {
30362
- case 0:
30363
- ids = entities && entities
30364
- .map(function (t) { return t.id; });
30365
- if (isEmptyArray(ids))
30366
- return [2 /*return*/]; // stop, if nothing else to do
30367
- now = Date.now();
30368
- if (this._debug)
30369
- console.debug(this._logPrefix + "Deleting events... ids:", ids);
30370
- return [4 /*yield*/, this.graphql.mutate({
30371
- mutation: this.mutations.deleteByIds,
30372
- variables: {
30373
- ids: ids
30374
- },
30375
- update: function (proxy) {
30376
- // Remove from caches
30377
- _this.removeFromMutableCachedQueriesByIds(proxy, {
30378
- query: _this.queries.loadAll,
30379
- ids: ids
30380
- });
30381
- _this.removeFromMutableCachedQueriesByIds(proxy, {
30382
- query: _this.queries.loadAllWithContent,
30383
- ids: ids
30384
- });
30385
- if (_this._debug)
30386
- console.debug(_this._logPrefix + "Events deleted in " + (Date.now() - now) + "ms");
30387
- }
30388
- })];
30389
- case 1:
30390
- _b.sent();
30391
- return [2 /*return*/];
30392
- }
30393
- });
30394
- });
30322
+ return Promise.all(data
30323
+ .map(function (entity) { return _this.save(entity, options); }));
30395
30324
  };
30396
- AbstractUserEventService.prototype.save = function (entity, options) {
30325
+ /**
30326
+ * Save a userEvent entity
30327
+ *
30328
+ * @param entity
30329
+ */
30330
+ UserEventService.prototype.save = function (entity, options) {
30397
30331
  return __awaiter(this, void 0, void 0, function () {
30398
30332
  var isNew, json, now;
30399
30333
  var _this = this;
30400
- return __generator(this, function (_b) {
30401
- switch (_b.label) {
30334
+ return __generator(this, function (_a) {
30335
+ switch (_a.label) {
30402
30336
  case 0:
30403
30337
  this.fillDefaultProperties(entity);
30404
30338
  isNew = isNil(entity.id);
30405
30339
  json = entity.asObject();
30406
30340
  now = Date.now();
30407
30341
  if (this._debug)
30408
- console.debug(this._logPrefix + "Saving user event...", json);
30342
+ console.debug("[user-event-service] Saving user event...", json);
30409
30343
  return [4 /*yield*/, this.graphql.mutate({
30410
- mutation: this.mutations.save,
30344
+ mutation: SaveQuery,
30411
30345
  variables: {
30412
30346
  data: json
30413
30347
  },
30414
30348
  error: { code: SocialErrorCodes.SAVE_USER_EVENT_ERROR, message: 'SOCIAL.ERROR.SAVE_USER_EVENT_ERROR' },
30415
- update: function (proxy, _b) {
30416
- var data = _b.data;
30349
+ update: function (proxy, _a) {
30350
+ var data = _a.data;
30417
30351
  // Update entity
30418
30352
  var savedEntity = data && data.data;
30419
30353
  if (savedEntity) {
30420
30354
  if (_this._debug)
30421
- console.debug(_this._logPrefix + "User event saved in " + (Date.now() - now) + "ms", entity);
30355
+ console.debug("[user-event-service] User event saved in " + (Date.now() - now) + "ms", entity);
30422
30356
  _this.copyIdAndUpdateDate(savedEntity, entity);
30423
30357
  // Add to cache
30424
30358
  if (isNew) {
30425
30359
  _this.insertIntoMutableCachedQueries(proxy, {
30426
- query: _this.queries.loadAll,
30360
+ query: LoadAllQuery,
30427
30361
  data: Object.assign(Object.assign({}, savedEntity), { content: null })
30428
30362
  });
30429
30363
  _this.insertIntoMutableCachedQueries(proxy, {
30430
- query: _this.queries.loadAllWithContent,
30364
+ query: LoadAllWithContentQuery,
30431
30365
  data: savedEntity
30432
30366
  });
30433
30367
  }
@@ -30435,185 +30369,93 @@
30435
30369
  }
30436
30370
  })];
30437
30371
  case 1:
30438
- _b.sent();
30372
+ _a.sent();
30439
30373
  return [2 /*return*/, entity];
30440
30374
  }
30441
30375
  });
30442
30376
  });
30443
30377
  };
30444
- AbstractUserEventService.prototype.saveAll = function (data, opts) {
30445
- var _this = this;
30446
- return Promise.all(data
30447
- .map(function (entity) { return _this.save(entity, opts); }));
30448
- };
30449
- AbstractUserEventService.prototype.markAsRead = function (entity) {
30378
+ /**
30379
+ * Save many trips
30380
+ *
30381
+ * @param entities
30382
+ * @param opts
30383
+ */
30384
+ UserEventService.prototype.deleteAll = function (entities, opts) {
30450
30385
  return __awaiter(this, void 0, void 0, function () {
30451
- var onReadListeners, onReadListeners_1, onReadListeners_1_1, listener, e_1_1;
30452
- var e_1, _b;
30453
- return __generator(this, function (_c) {
30454
- switch (_c.label) {
30386
+ var ids, now;
30387
+ var _this = this;
30388
+ return __generator(this, function (_a) {
30389
+ switch (_a.label) {
30455
30390
  case 0:
30456
- onReadListeners = (this.listeners || []).filter(function (listener) { return !!listener.onRead; }).filter(function (listener) { return listener.accept(entity); });
30457
- if (!onReadListeners.length) return [3 /*break*/, 9];
30458
- _c.label = 1;
30391
+ ids = entities && entities
30392
+ .map(function (t) { return t.id; });
30393
+ if (isEmptyArray(ids))
30394
+ return [2 /*return*/]; // stop, if nothing else to do
30395
+ now = Date.now();
30396
+ if (this._debug)
30397
+ console.debug('[user-event-service] Deleting events... ids:', ids);
30398
+ return [4 /*yield*/, this.graphql.mutate({
30399
+ mutation: DeleteByIdsMutation,
30400
+ variables: {
30401
+ ids: ids
30402
+ },
30403
+ update: function (proxy) {
30404
+ // Remove from caches
30405
+ _this.removeFromMutableCachedQueriesByIds(proxy, {
30406
+ query: LoadAllQuery,
30407
+ ids: ids
30408
+ });
30409
+ _this.removeFromMutableCachedQueriesByIds(proxy, {
30410
+ query: LoadAllWithContentQuery,
30411
+ ids: ids
30412
+ });
30413
+ if (_this._debug)
30414
+ console.debug("[user-event-service] Events deleted in " + (Date.now() - now) + "ms");
30415
+ }
30416
+ })];
30459
30417
  case 1:
30460
- _c.trys.push([1, 6, 7, 8]);
30461
- onReadListeners_1 = __values(onReadListeners), onReadListeners_1_1 = onReadListeners_1.next();
30462
- _c.label = 2;
30463
- case 2:
30464
- if (!!onReadListeners_1_1.done) return [3 /*break*/, 5];
30465
- listener = onReadListeners_1_1.value;
30466
- return [4 /*yield*/, listener.onRead(entity)];
30467
- case 3:
30468
- _c.sent();
30469
- _c.label = 4;
30470
- case 4:
30471
- onReadListeners_1_1 = onReadListeners_1.next();
30472
- return [3 /*break*/, 2];
30473
- case 5: return [3 /*break*/, 8];
30474
- case 6:
30475
- e_1_1 = _c.sent();
30476
- e_1 = { error: e_1_1 };
30477
- return [3 /*break*/, 8];
30478
- case 7:
30479
- try {
30480
- if (onReadListeners_1_1 && !onReadListeners_1_1.done && (_b = onReadListeners_1.return)) _b.call(onReadListeners_1);
30481
- }
30482
- finally { if (e_1) throw e_1.error; }
30483
- return [7 /*endfinally*/];
30484
- case 8: return [3 /*break*/, 11];
30485
- case 9:
30486
- // Use default
30487
- return [4 /*yield*/, this.defaultMarkAsRead(entity)];
30488
- case 10:
30489
- // Use default
30490
- _c.sent();
30491
- _c.label = 11;
30492
- case 11: return [2 /*return*/];
30418
+ _a.sent();
30419
+ return [2 /*return*/];
30493
30420
  }
30494
30421
  });
30495
30422
  });
30496
30423
  };
30497
- AbstractUserEventService.prototype.registerListener = function (listener) {
30498
- if (!this.listeners)
30499
- this.listeners = [];
30500
- this.listeners.push(listener);
30501
- };
30502
- /* -- protected methods -- */
30503
- AbstractUserEventService.prototype.processUserEvent = function (source) {
30504
- var e_2, _b;
30505
- // Convert json source to IUserEvent
30506
- var target = this.fromObject(source);
30507
- // Get listeners
30508
- var listeners = (this.listeners || []).filter(function (listener) { return listener.onReceived; }).filter(function (listener) { return listener.accept(target); });
30509
- try {
30510
- for (var listeners_1 = __values(listeners), listeners_1_1 = listeners_1.next(); !listeners_1_1.done; listeners_1_1 = listeners_1.next()) {
30511
- var listener = listeners_1_1.value;
30512
- if (target) {
30513
- target = listener.onReceived(target);
30514
- }
30515
- else {
30516
- if (this._debug)
30517
- console.debug(this._logPrefix + "Event has been rejected by a listener", source);
30518
- break;
30519
- }
30520
- }
30521
- }
30522
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
30523
- finally {
30524
- try {
30525
- if (listeners_1_1 && !listeners_1_1.done && (_b = listeners_1.return)) _b.call(listeners_1);
30526
- }
30527
- finally { if (e_2) throw e_2.error; }
30528
- }
30529
- return target;
30530
- };
30531
- AbstractUserEventService.prototype.defaultMarkAsRead = function (userEvent) {
30424
+ /**
30425
+ * Delete userEvent entities
30426
+ */
30427
+ UserEventService.prototype.delete = function (data) {
30532
30428
  return __awaiter(this, void 0, void 0, function () {
30533
- return __generator(this, function (_b) {
30534
- switch (_b.label) {
30429
+ return __generator(this, function (_a) {
30430
+ switch (_a.label) {
30535
30431
  case 0:
30536
- if (!userEvent)
30537
- throw new Error(this._logPrefix + "Invalid event to save");
30538
- // set read date
30539
- userEvent.readDate = moment$6();
30540
- if (!(!userEvent.id || userEvent.id < 0)) return [3 /*break*/, 1];
30541
- if (this._debug)
30542
- console.debug(this._logPrefix + "Save local user event");
30543
- return [3 /*break*/, 3];
30544
- case 1: return [4 /*yield*/, this.save(userEvent)];
30545
- case 2:
30546
- _b.sent();
30547
- _b.label = 3;
30548
- case 3: return [2 /*return*/];
30432
+ if (!data)
30433
+ return [2 /*return*/]; // skip
30434
+ return [4 /*yield*/, this.deleteAll([data])];
30435
+ case 1:
30436
+ _a.sent();
30437
+ return [2 /*return*/];
30549
30438
  }
30550
30439
  });
30551
30440
  });
30552
30441
  };
30553
- AbstractUserEventService.prototype.defaultFilter = function () {
30554
- // By default
30555
- return {
30556
- recipients: [this.defaultRecipient()]
30557
- };
30558
- };
30559
- AbstractUserEventService.prototype.defaultRecipient = function () {
30560
- return this.accountService.person.pubkey;
30442
+ UserEventService.prototype.listenChanges = function (id, options) {
30443
+ // TODO
30444
+ console.warn('TODO: implement listen changes on user events');
30445
+ return rxjs.of();
30561
30446
  };
30562
- AbstractUserEventService.prototype.fillDefaultProperties = function (entity) {
30447
+ UserEventService.prototype.registerAction = function (definition) {
30448
+ console.info("[user-event-service] Registering action " + definition.name + " for " + definition.__typename);
30449
+ this._userEventActions.push(definition);
30563
30450
  };
30564
- AbstractUserEventService.prototype.unreadEvents = function (events) {
30565
- // default calculation on unread events from a list
30566
- if (isEmptyArray(events))
30567
- return undefined;
30568
- var lastReadDate = events
30569
- .filter(function (event) { return isNotNil(event.readDate); })
30570
- .reduce(function (lastDate, event) { return DateUtils.max(lastDate, event.readDate); }, undefined);
30571
- return events
30572
- .filter(function (event) { return event.creationDate.isSameOrAfter(lastReadDate); }).length;
30573
- };
30574
- AbstractUserEventService.prototype.copyIdAndUpdateDate = function (source, target) {
30575
- EntityUtils.copyIdAndUpdateDate(source, target);
30451
+ UserEventService.prototype.getActionsByTypename = function (typename) {
30452
+ return this._userEventActions.filter(function (def) { return def.__typename === typename; });
30576
30453
  };
30577
- return AbstractUserEventService;
30578
- }(BaseGraphqlService));
30579
- AbstractUserEventService.decorators = [
30580
- { type: i0.Directive }
30581
- ];
30582
- AbstractUserEventService.ctorParameters = function () { return [
30583
- { type: GraphqlService },
30584
- { type: AccountService },
30585
- { type: NetworkService },
30586
- { type: i1$2.TranslateService },
30587
- { type: undefined },
30588
- { type: undefined },
30589
- { type: undefined },
30590
- { type: Environment, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [ENVIRONMENT,] }] }
30591
- ]; };
30592
- var userEventQueries = {
30593
- loadAll: core.gql(templateObject_1$3 || (templateObject_1$3 = __makeTemplateObject(["\n query UserEvents($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...LightUserEventFragment\n }\n }\n ", "\n "], ["\n query UserEvents($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...LightUserEventFragment\n }\n }\n ", "\n "])), UserEventFragments.lightUserEvent),
30594
- loadAllWithContent: core.gql(templateObject_2$3 || (templateObject_2$3 = __makeTemplateObject(["\n query UserEventsWithContent($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...UserEventFragment\n }\n }\n ", "\n "], ["\n query UserEventsWithContent($filter: UserEventFilterVOInput, $page: PageInput){\n data: userEvents(filter: $filter, page: $page){\n ...UserEventFragment\n }\n }\n ", "\n "])), UserEventFragments.userEvent)
30595
- };
30596
- var userEventMutations = {
30597
- deleteByIds: core.gql(templateObject_3$2 || (templateObject_3$2 = __makeTemplateObject(["\n mutation DeleteUserEvents($ids:[Int]){\n deleteUserEvents(ids: $ids)\n }\n "], ["\n mutation DeleteUserEvents($ids:[Int]){\n deleteUserEvents(ids: $ids)\n }\n "]))),
30598
- save: core.gql(templateObject_4$2 || (templateObject_4$2 = __makeTemplateObject(["\n mutation SaveUserEvent($data: UserEventVOInput){\n data: saveUserEvent(userEvent: $data){\n ...UserEventFragment\n }\n }\n ", "\n "], ["\n mutation SaveUserEvent($data: UserEventVOInput){\n data: saveUserEvent(userEvent: $data){\n ...UserEventFragment\n }\n }\n ", "\n "])), UserEventFragments.userEvent)
30599
- };
30600
- var UserEventService = /** @class */ (function (_super) {
30601
- __extends(UserEventService, _super);
30602
- function UserEventService(graphql, accountService, network, translate, toastController, environment) {
30603
- var _this = _super.call(this, graphql, accountService, network, translate, userEventQueries, userEventMutations, undefined, environment) || this;
30604
- _this.graphql = graphql;
30605
- _this.accountService = accountService;
30606
- _this.network = network;
30607
- _this.translate = translate;
30608
- _this.toastController = toastController;
30609
- _this.environment = environment;
30610
- return _this;
30611
- }
30612
30454
  UserEventService.prototype.showToastErrorWithContext = function (opts) {
30613
30455
  return __awaiter(this, void 0, void 0, function () {
30614
30456
  var message, res, context, userEvent, err_1;
30615
- return __generator(this, function (_b) {
30616
- switch (_b.label) {
30457
+ return __generator(this, function (_a) {
30458
+ switch (_a.label) {
30617
30459
  case 0:
30618
30460
  message = opts.message || (opts.error && opts.error.message || opts.error);
30619
30461
  // Make sure message a string
@@ -30642,12 +30484,12 @@
30642
30484
  }]
30643
30485
  })];
30644
30486
  case 1:
30645
- res = _b.sent();
30487
+ res = _a.sent();
30646
30488
  if (!res || res.role !== 'send')
30647
30489
  return [2 /*return*/];
30648
- _b.label = 2;
30490
+ _a.label = 2;
30649
30491
  case 2:
30650
- _b.trys.push([2, 6, , 7]);
30492
+ _a.trys.push([2, 6, , 7]);
30651
30493
  if (this._debug)
30652
30494
  console.debug('Sending debug data...');
30653
30495
  context = opts && opts.context;
@@ -30657,15 +30499,15 @@
30657
30499
  if (!(context instanceof Promise)) return [3 /*break*/, 4];
30658
30500
  return [4 /*yield*/, context];
30659
30501
  case 3:
30660
- context = _b.sent();
30661
- _b.label = 4;
30502
+ context = _a.sent();
30503
+ _a.label = 4;
30662
30504
  case 4: return [4 /*yield*/, this.sendDataForDebug({
30663
30505
  message: message,
30664
30506
  error: opts.error || undefined,
30665
30507
  context: this.convertObjectToString(context)
30666
30508
  })];
30667
30509
  case 5:
30668
- userEvent = _b.sent();
30510
+ userEvent = _a.sent();
30669
30511
  console.info('Debug data successfully sent to admin', userEvent);
30670
30512
  this.showToast({
30671
30513
  type: 'info',
@@ -30674,7 +30516,7 @@
30674
30516
  });
30675
30517
  return [3 /*break*/, 7];
30676
30518
  case 6:
30677
- err_1 = _b.sent();
30519
+ err_1 = _a.sent();
30678
30520
  console.error('Error while sending debug data:', err_1);
30679
30521
  return [3 /*break*/, 7];
30680
30522
  case 7: return [2 /*return*/];
@@ -30684,16 +30526,13 @@
30684
30526
  };
30685
30527
  UserEventService.prototype.sendDataForDebug = function (data) {
30686
30528
  var userEvent = new exports.UserEvent();
30687
- userEvent.type = UserEventTypes.DEBUG_DATA;
30529
+ userEvent.eventType = UserEventTypes.DEBUG_DATA;
30688
30530
  userEvent.content = this.convertObjectToString(data);
30689
30531
  return this.save(userEvent);
30690
30532
  };
30691
30533
  UserEventService.prototype.asFilter = function (filter) {
30692
30534
  return exports.UserEventFilter.fromObject(filter);
30693
30535
  };
30694
- UserEventService.prototype.fromObject = function (source) {
30695
- return exports.UserEvent.fromObject(source);
30696
- };
30697
30536
  /* -- protected methods -- */
30698
30537
  UserEventService.prototype.convertObjectToString = function (data) {
30699
30538
  if (typeof data === 'string') {
@@ -30711,13 +30550,13 @@
30711
30550
  };
30712
30551
  UserEventService.prototype.showToast = function (opts) {
30713
30552
  return __awaiter(this, void 0, void 0, function () {
30714
- return __generator(this, function (_b) {
30715
- switch (_b.label) {
30553
+ return __generator(this, function (_a) {
30554
+ switch (_a.label) {
30716
30555
  case 0:
30717
30556
  if (!this.toastController)
30718
30557
  throw new Error('Missing toastController in component\'s constructor');
30719
30558
  return [4 /*yield*/, Toasts.show(this.toastController, this.translate, opts)];
30720
- case 1: return [2 /*return*/, _b.sent()];
30559
+ case 1: return [2 /*return*/, _a.sent()];
30721
30560
  }
30722
30561
  });
30723
30562
  });
@@ -30728,10 +30567,14 @@
30728
30567
  // TODO: compute sign
30729
30568
  console.warn('TODO: sign user event before sending');
30730
30569
  };
30570
+ UserEventService.prototype.copyIdAndUpdateDate = function (source, target) {
30571
+ EntityUtils.copyIdAndUpdateDate(source, target);
30572
+ };
30731
30573
  return UserEventService;
30732
- }(AbstractUserEventService));
30574
+ }(BaseGraphqlService));
30575
+ UserEventService.ɵprov = i0.ɵɵdefineInjectable({ factory: function UserEventService_Factory() { return new UserEventService(i0.ɵɵinject(GraphqlService), i0.ɵɵinject(AccountService), i0.ɵɵinject(NetworkService), i0.ɵɵinject(i1$2.TranslateService), i0.ɵɵinject(i1$5.ToastController), i0.ɵɵinject(ENVIRONMENT, 8)); }, token: UserEventService, providedIn: "root" });
30733
30576
  UserEventService.decorators = [
30734
- { type: i0.Injectable }
30577
+ { type: i0.Injectable, args: [{ providedIn: 'root' },] }
30735
30578
  ];
30736
30579
  UserEventService.ctorParameters = function () { return [
30737
30580
  { type: GraphqlService },
@@ -30745,7 +30588,7 @@
30745
30588
 
30746
30589
  var ICONS_MAP = {
30747
30590
  DEBUG_DATA: { matIcon: 'bug_report' },
30748
- INBOX_MESSAGE: { matIcon: 'mail' }
30591
+ INBOX_MESSAGE: { matIcon: 'mail' },
30749
30592
  };
30750
30593
  // TODO: refactor with a registration done by data service:
30751
30594
  // - userEventService.registerEventAction({__typename: 'TripVO', ...})
@@ -30813,7 +30656,7 @@
30813
30656
  }
30814
30657
  }));
30815
30658
  var filter = this.filter || new exports.UserEventFilter();
30816
- filter.recipients = [this.recipient];
30659
+ filter.recipient = this.recipient;
30817
30660
  this.setFilter(filter, { emitEvent: true });
30818
30661
  };
30819
30662
  UserEventsTable.prototype.start = function () {
@@ -30835,17 +30678,17 @@
30835
30678
  });
30836
30679
  };
30837
30680
  UserEventsTable.prototype.getIcon = function (source) {
30838
- return ICONS_MAP[source.type];
30681
+ return ICONS_MAP[source.eventType];
30839
30682
  };
30840
30683
  UserEventsTable.prototype.getDetail = function (source) {
30841
30684
  if (!source)
30842
30685
  return undefined;
30843
- if (source.content && source.type === UserEventTypes.DEBUG_DATA) {
30686
+ if (source.content && source.eventType === UserEventTypes.DEBUG_DATA) {
30844
30687
  var context = source.content.context;
30845
30688
  if (context && context.__typename) {
30846
- // const actions = this.service.getActionsByTypename(context.__typename);
30689
+ var actions = this.service.getActionsByTypename(context.__typename);
30847
30690
  return {
30848
- // actions,
30691
+ actions: actions,
30849
30692
  title: source.content.error && source.content.error.message || source.content.message,
30850
30693
  description: source.content.error && source.content.error.details || undefined
30851
30694
  };
@@ -30856,18 +30699,18 @@
30856
30699
  };
30857
30700
  UserEventsTable.prototype.doAction = function (action, row) {
30858
30701
  return __awaiter(this, void 0, void 0, function () {
30859
- var event, res, _a, err_1;
30702
+ var event, context, res, _a, err_1;
30860
30703
  return __generator(this, function (_b) {
30861
30704
  switch (_b.label) {
30862
30705
  case 0:
30863
30706
  event = row.currentData;
30864
- // const context = event.content && event.content.context;
30707
+ context = event.content && event.content.context;
30865
30708
  this.markAsLoading();
30866
30709
  if (!(action && typeof action.executeAction === 'function')) return [3 /*break*/, 7];
30867
30710
  _b.label = 1;
30868
30711
  case 1:
30869
30712
  _b.trys.push([1, 5, 6, 7]);
30870
- res = action.executeAction(event /*, context*/);
30713
+ res = action.executeAction(event, context);
30871
30714
  if (!(res instanceof Promise)) return [3 /*break*/, 3];
30872
30715
  return [4 /*yield*/, res];
30873
30716
  case 2:
@@ -30899,18 +30742,13 @@
30899
30742
  selector: 'app-user-events-table',
30900
30743
  template: "\n<!-- Type = options menu -->\n<mat-menu #optionsMenu=\"matMenu\" xPosition=\"after\">\n\n <!-- display columns -->\n <button mat-menu-item\n (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n</mat-menu>\n\n<!-- top header -->\n<mat-toolbar>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n\n <button mat-icon-button [title]=\"'COMMON.BTN_REFRESH'|translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\n\n <!-- delete -->\n <button mat-icon-button class=\"hidden-xs hidden-sm\" *ngIf=\"canDelete\"\n [title]=\"'COMMON.BTN_DELETE'|translate\" (click)=\"deleteSelection($event)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" hidden-xs hidden-sm hidden-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS'|translate\"\n [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n</mat-toolbar>\n\n\n<mat-table [dataSource]=\"dataSource\" matSort\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear [trackBy]=\"trackByFn\">\n\n <!-- select -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\" [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <!-- id -->\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef mat-sort-header [class.cdk-visually-hidden]=\"!isAdmin\">\n <app-loading-spinner [loading]=\"loadingSubject|async\"><ion-label>#</ion-label></app-loading-spinner>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!isAdmin\">{{ row.currentData.id | mathAbs }}</mat-cell>\n </ng-container>\n\n <!-- creationDate -->\n <ng-container matColumnDef=\"creationDate\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.CREATION_DATE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ion-text>\n {{row.currentData.creationDate | dateFromNow }}<br/>\n <ion-text color=\"medium\"><small>{{row.currentData.creationDate | dateFormat: {time: true} }}</small></ion-text>\n </ion-text>\n </mat-cell>\n </ng-container>\n\n <!-- icon -->\n <ng-container matColumnDef=\"icon\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getIcon(row.currentData); let details\">\n <ion-icon slot=\"start\" *ngIf=\"details.icon\" [name]=\"details.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"details.matIcon\">{{details.matIcon}}</mat-icon>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- event type -->\n <ng-container matColumnDef=\"eventType\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.EVENT_TYPE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <span>{{'SOCIAL.USER_EVENT.TYPE_ENUM.' + row.currentData.eventType | translate}}</span>\n </mat-cell>\n </ng-container>\n\n <!-- message -->\n <ng-container matColumnDef=\"message\">\n <mat-header-cell *matHeaderCellDef>\n <ion-label translate>SOCIAL.USER_EVENT.MESSAGE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <ion-text [innerHTML]=\"details.title|translate\">\n </ion-text>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- Actions buttons column -->\n <ng-container matColumnDef=\"actions\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <button mat-icon-button color=\"light\"\n *ngFor=\"let action of details.actions\"\n [title]=\"action.title |translate\"\n [color]=\"action.color\"\n (click)=\"doAction(action, row)\">\n <ion-icon slot=\"start\" *ngIf=\"action.icon\" [name]=\"action.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"action.matIcon\">{{action.matIcon}}</mat-icon>\n </button>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n class=\"mat-row-disabled\"\n (click)=\"clickRow($event, row)\"></mat-row>\n\n</mat-table>\n\n<ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col class=\"ion-no-padding\" size=\"auto\">\n <mat-paginator [length]=\"totalRowCount\" [pageSize]=\"defaultPageSize\" [pageSizeOptions]=\"defaultPageSizeOptions\" showFirstLastButtons>\n </mat-paginator>\n </ion-col>\n</ion-row>\n",
30901
30744
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
30902
- providers: [
30903
- {
30904
- provide: UserEventServiceToken, useClass: UserEventService
30905
- }
30906
- ],
30907
30745
  styles: [".mat-header-row .mat-column-icon,.mat-row .mat-column-icon{max-width:40px;padding-left:0}.mat-header-row .mat-column-icon ion-icon,.mat-header-row .mat-column-icon mat-icon,.mat-row .mat-column-icon ion-icon,.mat-row .mat-column-icon mat-icon{font-size:1.2em;height:1.2em;width:1.2em}.mat-header-row .mat-column-creationDate,.mat-row .mat-column-creationDate{min-width:100px;max-width:120px}"]
30908
30746
  },] }
30909
30747
  ];
30910
30748
  UserEventsTable.ctorParameters = function () { return [
30911
30749
  { type: i0.Injector },
30912
30750
  { type: AccountService },
30913
- { type: undefined, decorators: [{ type: i0.Inject, args: [UserEventServiceToken,] }] },
30751
+ { type: UserEventService },
30914
30752
  { type: EntitiesStorage },
30915
30753
  { type: i0.ChangeDetectorRef },
30916
30754
  { type: undefined, decorators: [{ type: i0.Inject, args: [ENVIRONMENT,] }] }
@@ -30922,167 +30760,6 @@
30922
30760
  defaultSortDirection: [{ type: i0.Input }]
30923
30761
  };
30924
30762
 
30925
- var UserEventNotificationList = /** @class */ (function () {
30926
- function UserEventNotificationList(popoverController) {
30927
- this.popoverController = popoverController;
30928
- }
30929
- UserEventNotificationList.prototype.ngOnInit = function () {
30930
- };
30931
- UserEventNotificationList.prototype.read = function ($event, userEvent) {
30932
- var _a;
30933
- if (userEvent === null || userEvent === void 0 ? void 0 : userEvent.readDate)
30934
- return;
30935
- (_a = this.readEvent) === null || _a === void 0 ? void 0 : _a.emit(userEvent);
30936
- };
30937
- UserEventNotificationList.prototype.executeAction = function (action, userEvent) {
30938
- // Execute then close popover
30939
- action.executeAction(userEvent);
30940
- this.dismiss();
30941
- };
30942
- UserEventNotificationList.prototype.dismiss = function () {
30943
- this.popoverController.dismiss();
30944
- };
30945
- return UserEventNotificationList;
30946
- }());
30947
- UserEventNotificationList.decorators = [
30948
- { type: i0.Component, args: [{
30949
- selector: 'app-user-event-notification-list',
30950
- template: "\n<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!(userEvents | async)?.length\">\n {{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}\n </ion-item>\n <ion-item\n *ngFor=\"let userEvent of userEvents | async\"\n (click)=\"read($event, userEvent)\"\n >\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"userEvent.avatar; else avatarIcon\" src=\"{{ userEvent.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"userEvent.avatarIcon\"\n [ref]=\"userEvent.avatarIcon\"\n height=\"40\"\n width=\"40\"\n ></app-icon>\n </ng-template>\n\n </ion-avatar>\n\n <ion-grid class=\"ion-no-margin ion-no-padding\">\n <ion-row>\n <ion-col>\n <p [class.unread]=\"!userEvent.readDate\">\n {{userEvent.message}}\n </p>\n </ion-col>\n </ion-row>\n <ion-row *ngIf=\"userEvent.actions?.length\">\n <ion-col>\n <p>\n <span *ngFor=\"let action of userEvent.actions\">\n <a\n [style.margin-right.px]=\"8\"\n [style.cursor]=\"'pointer'\"\n (click)=\"executeAction(action, userEvent)\"\n >\n {{ '&#10142;&nbsp;' + action.name}}\n </a>\n </span>\n </p>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <app-icon\n *ngIf=\"userEvent.icon\"\n [ref]=\"userEvent.icon\"\n height=\"16\"\n width=\"16\"\n [style.vertical-align]=\"'sub'\"\n ></app-icon>\n <small>\n <span>{{userEvent.creationDate|dateFromNow}}</span>\n <span [style.color]=\"'gray'\">{{ ' | ' + (userEvent.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
30951
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}.unread{font-weight:700}"]
30952
- },] }
30953
- ];
30954
- UserEventNotificationList.ctorParameters = function () { return [
30955
- { type: i1$5.PopoverController }
30956
- ]; };
30957
- UserEventNotificationList.propDecorators = {
30958
- titleI18n: [{ type: i0.Input }],
30959
- userEvents: [{ type: i0.Input }],
30960
- readEvent: [{ type: i0.Output }]
30961
- };
30962
-
30963
- var UserEventNotificationComponent = /** @class */ (function () {
30964
- function UserEventNotificationComponent(userEventService, accountService, popoverController, cd) {
30965
- this.userEventService = userEventService;
30966
- this.accountService = accountService;
30967
- this.popoverController = popoverController;
30968
- this.cd = cd;
30969
- this.debug = false;
30970
- this.titleI18n = 'SOCIAL.USER_EVENT.NOTIFICATION.TITLE';
30971
- this.disabled = false;
30972
- this.userEventsSubject = new rxjs.BehaviorSubject(undefined);
30973
- this._subscriptions = new rxjs.Subscription();
30974
- this._logPrefix = '[user-event-notification] ';
30975
- this._readEvent = new i0.EventEmitter();
30976
- }
30977
- Object.defineProperty(UserEventNotificationComponent.prototype, "count", {
30978
- get: function () {
30979
- var _a;
30980
- return (_a = this.userEventService) === null || _a === void 0 ? void 0 : _a.userEventCount.pipe(operators.map(function (value) { return value === 0 ? undefined : value; }));
30981
- },
30982
- enumerable: false,
30983
- configurable: true
30984
- });
30985
- UserEventNotificationComponent.prototype.ngOnInit = function () {
30986
- var _this = this;
30987
- if (isNil(this.userEventService)) {
30988
- console.warn(this._logPrefix + "No service injected");
30989
- this.disabled = true;
30990
- return;
30991
- }
30992
- this._subscriptions.add(this.userEventService.watchAll(0, 10, 'creationDate', "desc").subscribe(function (value) {
30993
- var data = value.data;
30994
- if (_this.debug) {
30995
- console.debug(_this._logPrefix + "Receiving user events", data);
30996
- }
30997
- _this.userEventsSubject.next(data);
30998
- }));
30999
- this._readEvent.subscribe(function (value) {
31000
- _this.userEventService.markAsRead(value);
31001
- });
31002
- };
31003
- UserEventNotificationComponent.prototype.showList = function (event) {
31004
- return __awaiter(this, void 0, void 0, function () {
31005
- var popover;
31006
- return __generator(this, function (_b) {
31007
- switch (_b.label) {
31008
- case 0: return [4 /*yield*/, this.popoverController.create({
31009
- component: UserEventNotificationList,
31010
- componentProps: {
31011
- titleI18n: this.titleI18n,
31012
- userEvents: this.userEventsSubject,
31013
- readEvent: this._readEvent
31014
- },
31015
- backdropDismiss: true,
31016
- keyboardClose: true,
31017
- event: event,
31018
- translucent: true,
31019
- cssClass: 'popover-large'
31020
- })];
31021
- case 1:
31022
- popover = _b.sent();
31023
- return [4 /*yield*/, popover.present()];
31024
- case 2:
31025
- _b.sent();
31026
- return [2 /*return*/];
31027
- }
31028
- });
31029
- });
31030
- };
31031
- UserEventNotificationComponent.prototype.markForCheck = function () {
31032
- this.cd.markForCheck();
31033
- };
31034
- UserEventNotificationComponent.prototype.ngOnDestroy = function () {
31035
- if (this.debug) {
31036
- console.debug(this._logPrefix + "Destroying");
31037
- }
31038
- this._subscriptions.unsubscribe();
31039
- };
31040
- return UserEventNotificationComponent;
31041
- }());
31042
- UserEventNotificationComponent.decorators = [
31043
- { type: i0.Component, args: [{
31044
- selector: 'app-user-event-notification-component',
31045
- template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n [matBadge]=\"count | async\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n >notifications\n </mat-icon>\n</button>\n\n",
31046
- changeDetection: i0.ChangeDetectionStrategy.OnPush,
31047
- styles: [""]
31048
- },] }
31049
- ];
31050
- UserEventNotificationComponent.ctorParameters = function () { return [
31051
- { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [UserEventServiceToken,] }] },
31052
- { type: AccountService },
31053
- { type: i1$5.PopoverController },
31054
- { type: i0.ChangeDetectorRef }
31055
- ]; };
31056
- UserEventNotificationComponent.propDecorators = {
31057
- debug: [{ type: i0.Input }],
31058
- titleI18n: [{ type: i0.Input }],
31059
- disabled: [{ type: i0.Input }]
31060
- };
31061
-
31062
- var UserEventModule = /** @class */ (function () {
31063
- function UserEventModule() {
31064
- }
31065
- return UserEventModule;
31066
- }());
31067
- UserEventModule.decorators = [
31068
- { type: i0.NgModule, args: [{
31069
- imports: [
31070
- i1$4.CommonModule,
31071
- CoreModule,
31072
- SharedModule
31073
- ],
31074
- declarations: [
31075
- UserEventsTable,
31076
- UserEventNotificationComponent,
31077
- UserEventNotificationList,
31078
- ],
31079
- exports: [
31080
- UserEventsTable,
31081
- UserEventNotificationComponent
31082
- ]
31083
- },] }
31084
- ];
31085
-
31086
30763
  var MessageTypes = {
31087
30764
  INBOX_MESSAGE: 'INBOX_MESSAGE',
31088
30765
  EMAIL: 'EMAIL',
@@ -31316,12 +30993,12 @@
31316
30993
  canSelectType: [{ type: i0.Input }]
31317
30994
  };
31318
30995
 
31319
- var MessageModule = /** @class */ (function () {
31320
- function MessageModule() {
30996
+ var SocialModule = /** @class */ (function () {
30997
+ function SocialModule() {
31321
30998
  }
31322
- return MessageModule;
30999
+ return SocialModule;
31323
31000
  }());
31324
- MessageModule.decorators = [
31001
+ SocialModule.decorators = [
31325
31002
  { type: i0.NgModule, args: [{
31326
31003
  imports: [
31327
31004
  i1$4.CommonModule,
@@ -31329,342 +31006,19 @@
31329
31006
  SharedModule
31330
31007
  ],
31331
31008
  declarations: [
31009
+ UserEventsTable,
31332
31010
  MessageModal,
31333
31011
  MessageForm
31334
31012
  ],
31335
31013
  exports: [
31014
+ UserEventsTable,
31336
31015
  MessageModal
31337
31016
  ]
31338
31017
  },] }
31339
31018
  ];
31340
31019
 
31341
- var JobProgression_1;
31342
- // todo use entity
31343
- var Job = /** @class */ (function () {
31344
- function Job() {
31345
- }
31346
- return Job;
31347
- }());
31348
- // @dynamic
31349
- exports.JobProgression = JobProgression_1 = /** @class */ (function (_super) {
31350
- __extends(JobProgression, _super);
31351
- function JobProgression() {
31352
- return _super.call(this, JobProgression_1.TYPENAME) || this;
31353
- }
31354
- JobProgression.prototype.fromObject = function (source) {
31355
- _super.prototype.fromObject.call(this, source);
31356
- this.message = source.message;
31357
- this.current = source.current;
31358
- this.total = source.total;
31359
- };
31360
- return JobProgression;
31361
- }(Entity));
31362
- exports.JobProgression = JobProgression_1 = __decorate([
31363
- EntityClass({ typename: 'JobProgressionVO' })
31364
- ], exports.JobProgression);
31365
-
31366
- var JobProgressionServiceToken = new i0.InjectionToken('JobProgressionService');
31367
- var jobProgressionSubscription = core.gql(templateObject_1$4 || (templateObject_1$4 = __makeTemplateObject(["subscription UpdateJobProgression($id: Int!, $interval: Int){\n data: updateJobProgression(id: $id, interval: $interval) {\n id\n message\n current\n total\n }\n}"], ["subscription UpdateJobProgression($id: Int!, $interval: Int){\n data: updateJobProgression(id: $id, interval: $interval) {\n id\n message\n current\n total\n }\n}"])));
31368
- var JobProgressionService = /** @class */ (function (_super) {
31369
- __extends(JobProgressionService, _super);
31370
- function JobProgressionService(graphql, environment) {
31371
- var _this = _super.call(this, graphql, environment) || this;
31372
- _this.graphql = graphql;
31373
- _this.environment = environment;
31374
- _this._logPrefix = '[job-progression-service] ';
31375
- // For DEV only
31376
- _this._debug = !(environment === null || environment === void 0 ? void 0 : environment.production);
31377
- return _this;
31378
- }
31379
- JobProgressionService.prototype.listenChanges = function (id, options) {
31380
- var _this = this;
31381
- if (isNil(id))
31382
- throw new Error(this._logPrefix + "Missing argument 'id'");
31383
- if (this._debug)
31384
- console.debug(this._logPrefix + "[WS] Listening changes for job progression {" + id + "}...");
31385
- return this.graphql.subscribe({
31386
- query: jobProgressionSubscription,
31387
- fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
31388
- variables: { id: id, interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
31389
- error: { code: SocialErrorCodes.SUBSCRIBE_JOB_PROGRESSION_ERROR, message: 'SOCIAL.ERROR.SUBSCRIBE_JOB_PROGRESSION_ERROR' }
31390
- }).pipe(operators.map(function (_a) {
31391
- var data = _a.data;
31392
- var progression = data && exports.JobProgression.fromObject(data);
31393
- if (progression && _this._debug)
31394
- console.debug(_this._logPrefix + "Job progression " + id + " updated on server", progression);
31395
- return progression;
31396
- }));
31397
- };
31398
- return JobProgressionService;
31399
- }(BaseGraphqlService));
31400
- JobProgressionService.decorators = [
31401
- { type: i0.Injectable }
31402
- ];
31403
- JobProgressionService.ctorParameters = function () { return [
31404
- { type: GraphqlService },
31405
- { type: Environment, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [ENVIRONMENT,] }] }
31406
- ]; };
31407
- var templateObject_1$4;
31408
-
31409
- var JobProgressionList = /** @class */ (function () {
31410
- function JobProgressionList() {
31411
- }
31412
- JobProgressionList.prototype.ngOnInit = function () {
31413
- };
31414
- return JobProgressionList;
31415
- }());
31416
- JobProgressionList.decorators = [
31417
- { type: i0.Component, args: [{
31418
- selector: 'app-job-progression-list',
31419
- template: "<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!jobProgressions?.length\">\n {{'SOCIAL.JOB.PROGRESSION.EMPTY' | translate}}\n </ion-item>\n <ion-item *ngFor=\"let jobProgression of jobProgressions\">\n <ion-grid class=\"ion-no-margin\">\n <ion-row>\n <ion-col>\n {{jobProgression.message}}\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-progress-bar\n [value]=\"jobProgression.total > 0 ? jobProgression.current / jobProgression.total : undefined\"\n [type]=\"jobProgression.total > 0 ? 'determinate' : 'indeterminate'\">\n </ion-progress-bar>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
31420
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}"]
31421
- },] }
31422
- ];
31423
- JobProgressionList.ctorParameters = function () { return []; };
31424
- JobProgressionList.propDecorators = {
31425
- titleI18n: [{ type: i0.Input }],
31426
- jobProgressions: [{ type: i0.Input }]
31427
- };
31428
-
31429
- var JobProgressionComponent = /** @class */ (function () {
31430
- function JobProgressionComponent(jobProgressionService, popoverController, cd) {
31431
- this.jobProgressionService = jobProgressionService;
31432
- this.popoverController = popoverController;
31433
- this.cd = cd;
31434
- this.debug = false;
31435
- this.titleI18n = 'SOCIAL.JOB.PROGRESSION.TITLE';
31436
- this.jobFinished = new i0.EventEmitter();
31437
- this.disabled = true;
31438
- this.color = 'accent';
31439
- this.mode = 'determinate';
31440
- this.value = 0;
31441
- this.jobProgressions = [];
31442
- this._subscriptions = new rxjs.Subscription();
31443
- this._subscriptionsById = {};
31444
- this._logPrefix = '[job-progression] ';
31445
- }
31446
- JobProgressionComponent.prototype.ngOnInit = function () {
31447
- var _a, _b, _c, _d;
31448
- if (isNil(this.jobProgressionService)) {
31449
- console.warn(this._logPrefix + "No service injected");
31450
- }
31451
- // parse options
31452
- this.autoHide = toBoolean((_a = this.options) === null || _a === void 0 ? void 0 : _a.autoHide, false);
31453
- this.visible = !this.autoHide;
31454
- this.autoHideDelay = toNumber((_b = this.options) === null || _b === void 0 ? void 0 : _b.autoHideDelay, 1000);
31455
- this.autoRemove = toBoolean((_c = this.options) === null || _c === void 0 ? void 0 : _c.autoRemove, true);
31456
- this.autoRemoveDelay = toNumber((_d = this.options) === null || _d === void 0 ? void 0 : _d.autoRemoveDelay, 1000);
31457
- };
31458
- JobProgressionComponent.prototype.addJob = function (id) {
31459
- var _this = this;
31460
- if (isNil(this.jobProgressionService)) {
31461
- console.warn(this._logPrefix + "No service injected. Can't add a job");
31462
- return;
31463
- }
31464
- if (this.debug) {
31465
- console.debug(this._logPrefix + "Add job id=" + id);
31466
- }
31467
- if (!!this.getProgression(id)) {
31468
- console.warn(this._logPrefix + "Job (id=" + id + ") already present");
31469
- return;
31470
- }
31471
- this.disabled = false;
31472
- var sub = this.jobProgressionService.listenChanges(id)
31473
- .pipe(operators.filter(function (progression) {
31474
- if (id !== progression.id) {
31475
- console.error(_this._logPrefix + "Job progression (id=" + progression.id + ") doesn't match expected job (id=" + id + ")");
31476
- return false;
31477
- }
31478
- return true;
31479
- }), operators.map(function (progression) {
31480
- // Ensure visible
31481
- _this.visible = true;
31482
- // Get current progression object
31483
- var currentProgression = _this.getProgression(id);
31484
- if (!currentProgression) {
31485
- // add it
31486
- _this.jobProgressions.push(progression);
31487
- if (_this.debug) {
31488
- console.debug(_this._logPrefix + "Progression added id=" + id, progression);
31489
- }
31490
- }
31491
- else {
31492
- // update current
31493
- Object.assign(currentProgression, progression);
31494
- if (_this.debug) {
31495
- console.debug(_this._logPrefix + "Progression updated id=" + id, progression);
31496
- }
31497
- }
31498
- return progression;
31499
- }))
31500
- .subscribe(function (progression) {
31501
- // update value
31502
- _this.updateValue();
31503
- // job finished
31504
- if (progression.total > 0 && progression.current == progression.total) {
31505
- if (_this.debug) {
31506
- console.debug(_this._logPrefix + "Finished job id=" + progression.id);
31507
- }
31508
- // emit event
31509
- _this.jobFinished.emit(progression.id);
31510
- if (_this.autoRemove) {
31511
- setTimeout(function () {
31512
- var _a;
31513
- _this.removeJob(progression.id);
31514
- // If last job
31515
- if (_this.autoHide && !((_a = _this.jobProgressions) === null || _a === void 0 ? void 0 : _a.length)) {
31516
- setTimeout(function () {
31517
- _this.visible = false;
31518
- _this.markForCheck();
31519
- }, _this.autoHideDelay);
31520
- }
31521
- }, _this.autoRemoveDelay);
31522
- }
31523
- }
31524
- });
31525
- this._subscriptionsById[id] = sub;
31526
- this._subscriptions.add(sub);
31527
- };
31528
- JobProgressionComponent.prototype.removeJob = function (id) {
31529
- if (this.debug) {
31530
- console.debug(this._logPrefix + "Remove job id=" + id);
31531
- }
31532
- var sub = this._subscriptionsById[id];
31533
- if (sub) {
31534
- this._subscriptions.remove(sub);
31535
- sub.unsubscribe();
31536
- }
31537
- var progression = this.getProgression(id);
31538
- if (progression) {
31539
- this.jobProgressions.splice(this.jobProgressions.indexOf(progression), 1);
31540
- }
31541
- this.updateValue();
31542
- };
31543
- JobProgressionComponent.prototype.getProgression = function (id) {
31544
- return this.jobProgressions.find(function (progression) { return progression.id === id; });
31545
- };
31546
- JobProgressionComponent.prototype.updateValue = function () {
31547
- if (this.debug) {
31548
- console.debug(this._logPrefix + "Updating value");
31549
- }
31550
- var value = 0;
31551
- var nbProgression = arraySize(this.jobProgressions);
31552
- var allIndeterminate = nbProgression > 0;
31553
- this.jobProgressions.forEach(function (progression) {
31554
- var indeterminate = progression.total === 0;
31555
- allIndeterminate = allIndeterminate && indeterminate;
31556
- if (!indeterminate) {
31557
- value = value + progression.current * 100 / progression.total;
31558
- }
31559
- });
31560
- this.value = nbProgression > 0 ? value / nbProgression : 0;
31561
- this.mode = allIndeterminate ? 'indeterminate' : 'determinate';
31562
- if (this.debug) {
31563
- console.debug(this._logPrefix + "Setting value=" + this.value + ", mode=" + this.mode);
31564
- }
31565
- this.markForCheck();
31566
- };
31567
- JobProgressionComponent.prototype.showList = function (event) {
31568
- return __awaiter(this, void 0, void 0, function () {
31569
- var popover;
31570
- return __generator(this, function (_e) {
31571
- switch (_e.label) {
31572
- case 0: return [4 /*yield*/, this.popoverController.create({
31573
- component: JobProgressionList,
31574
- componentProps: {
31575
- titleI18n: this.titleI18n,
31576
- jobProgressions: this.jobProgressions
31577
- },
31578
- backdropDismiss: true,
31579
- keyboardClose: true,
31580
- event: event,
31581
- translucent: true,
31582
- cssClass: 'popover-large'
31583
- })];
31584
- case 1:
31585
- popover = _e.sent();
31586
- return [4 /*yield*/, popover.present()];
31587
- case 2:
31588
- _e.sent();
31589
- return [2 /*return*/];
31590
- }
31591
- });
31592
- });
31593
- };
31594
- JobProgressionComponent.prototype.markForCheck = function () {
31595
- this.cd.markForCheck();
31596
- };
31597
- JobProgressionComponent.prototype.ngOnDestroy = function () {
31598
- if (this.debug) {
31599
- console.debug(this._logPrefix + "Destroying");
31600
- }
31601
- this._subscriptions.unsubscribe();
31602
- };
31603
- return JobProgressionComponent;
31604
- }());
31605
- JobProgressionComponent.decorators = [
31606
- { type: i0.Component, args: [{
31607
- selector: 'app-job-progression',
31608
- template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n *ngIf=\"visible\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n [matBadge]=\"jobProgressions?.length\"\n [matBadgeHidden]=\"!jobProgressions?.length\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n >{{ disabled || jobProgressions?.length ? 'schedule' : 'task_alt' }}\n </mat-icon>\n <mat-spinner\n #spinner\n *ngIf=\"jobProgressions?.length\"\n class=\"floating-spinner\"\n [color]=\"color\"\n [mode]=\"mode\"\n [value]=\"value\"\n diameter=\"30\"\n strokeWidth=\"3\"\n ></mat-spinner>\n</button>\n\n",
31609
- changeDetection: i0.ChangeDetectionStrategy.OnPush,
31610
- styles: [".floating-spinner{position:absolute;top:6px;left:5px}"]
31611
- },] }
31612
- ];
31613
- JobProgressionComponent.ctorParameters = function () { return [
31614
- { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [JobProgressionServiceToken,] }] },
31615
- { type: i1$5.PopoverController },
31616
- { type: i0.ChangeDetectorRef }
31617
- ]; };
31618
- JobProgressionComponent.propDecorators = {
31619
- debug: [{ type: i0.Input }],
31620
- titleI18n: [{ type: i0.Input }],
31621
- options: [{ type: i0.Input }],
31622
- jobFinished: [{ type: i0.Output }]
31623
- };
31624
-
31625
- var JobModule = /** @class */ (function () {
31626
- function JobModule() {
31627
- }
31628
- return JobModule;
31629
- }());
31630
- JobModule.decorators = [
31631
- { type: i0.NgModule, args: [{
31632
- imports: [
31633
- i1$4.CommonModule,
31634
- SharedModule,
31635
- i1$2.TranslateModule.forChild(),
31636
- ],
31637
- declarations: [
31638
- JobProgressionComponent,
31639
- JobProgressionList
31640
- ],
31641
- exports: [
31642
- JobProgressionComponent
31643
- ]
31644
- },] }
31645
- ];
31646
-
31647
- var SocialModuleOptionsToken = new i0.InjectionToken("SocialModuleOptions");
31648
- var SocialModule = /** @class */ (function () {
31649
- function SocialModule() {
31650
- }
31651
- return SocialModule;
31652
- }());
31653
- SocialModule.decorators = [
31654
- { type: i0.NgModule, args: [{
31655
- imports: [
31656
- i1$4.CommonModule,
31657
- CoreModule,
31658
- SharedModule,
31659
- UserEventModule,
31660
- JobModule,
31661
- MessageModule,
31662
- ],
31663
- },] }
31664
- ];
31665
-
31666
31020
  var Mutations = {
31667
- send: core.gql(templateObject_1$5 || (templateObject_1$5 = __makeTemplateObject(["mutation SendMessage($data: MessageVOInput){\n done: sendMessage(message: $data)\n }"], ["mutation SendMessage($data: MessageVOInput){\n done: sendMessage(message: $data)\n }"])))
31021
+ send: core.gql(templateObject_1$4 || (templateObject_1$4 = __makeTemplateObject(["mutation SendMessage($data: MessageVOInput){\n done: sendMessage(message: $data)\n }"], ["mutation SendMessage($data: MessageVOInput){\n done: sendMessage(message: $data)\n }"])))
31668
31022
  };
31669
31023
  var MessageService = /** @class */ (function (_super) {
31670
31024
  __extends(MessageService, _super);
@@ -31748,7 +31102,7 @@
31748
31102
  { type: i1$5.ToastController },
31749
31103
  { type: Environment, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [ENVIRONMENT,] }] }
31750
31104
  ]; };
31751
- var templateObject_1$5;
31105
+ var templateObject_1$4;
31752
31106
 
31753
31107
  var PersonFilter_1;
31754
31108
  // @dynamic
@@ -31807,7 +31161,7 @@
31807
31161
  ], exports.PersonFilter);
31808
31162
 
31809
31163
  var PersonFragments = {
31810
- person: core.gql(templateObject_1$6 || (templateObject_1$6 = __makeTemplateObject(["fragment PersonFragment on PersonVO {\n id\n firstName\n lastName\n email\n pubkey\n avatar\n statusId\n updateDate\n creationDate\n profiles\n username\n usernameExtranet\n department {\n id\n label\n name\n logo\n __typename\n }\n __typename\n }"], ["fragment PersonFragment on PersonVO {\n id\n firstName\n lastName\n email\n pubkey\n avatar\n statusId\n updateDate\n creationDate\n profiles\n username\n usernameExtranet\n department {\n id\n label\n name\n logo\n __typename\n }\n __typename\n }"])))
31164
+ person: core.gql(templateObject_1$5 || (templateObject_1$5 = __makeTemplateObject(["fragment PersonFragment on PersonVO {\n id\n firstName\n lastName\n email\n pubkey\n avatar\n statusId\n updateDate\n creationDate\n profiles\n username\n usernameExtranet\n department {\n id\n label\n name\n logo\n __typename\n }\n __typename\n }"], ["fragment PersonFragment on PersonVO {\n id\n firstName\n lastName\n email\n pubkey\n avatar\n statusId\n updateDate\n creationDate\n profiles\n username\n usernameExtranet\n department {\n id\n label\n name\n logo\n __typename\n }\n __typename\n }"])))
31811
31165
  };
31812
31166
  // Load persons query
31813
31167
  var PersonQueries = {
@@ -31947,7 +31301,7 @@
31947
31301
  { type: NetworkService },
31948
31302
  { type: EntitiesStorage }
31949
31303
  ]; };
31950
- var templateObject_1$6, templateObject_2$4, templateObject_3$3, templateObject_4$3, templateObject_5$2;
31304
+ var templateObject_1$5, templateObject_2$4, templateObject_3$3, templateObject_4$3, templateObject_5$2;
31951
31305
 
31952
31306
  var PersonValidatorService = /** @class */ (function () {
31953
31307
  function PersonValidatorService(formBuilder, accountValidatorService) {
@@ -32357,10 +31711,12 @@
32357
31711
  };
32358
31712
  AutocompleteTestPage.prototype.ngAfterViewInit = function () {
32359
31713
  var _this = this;
32360
- setTimeout(function () {
32361
- _this.farEntityField.suggestLengthThreshold = 2;
32362
- _this.farEntityField.reloadItems();
32363
- }, 2000);
31714
+ if (this.farEntityField) {
31715
+ setTimeout(function () {
31716
+ _this.farEntityField.suggestLengthThreshold = 2;
31717
+ _this.farEntityField.reloadItems();
31718
+ }, 2000);
31719
+ }
32364
31720
  setTimeout(function () { return _this.loadData(); }, 1000);
32365
31721
  };
32366
31722
  // Load the form with data
@@ -32467,7 +31823,7 @@
32467
31823
  AutocompleteTestPage.decorators = [
32468
31824
  { type: i0.Component, args: [{
32469
31825
  selector: 'app-autocomplete-test',
32470
- template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Autocomplete field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <!-- Tab nav - mobile/desktop mode -->\n <nav mat-tab-nav-bar>\n <a mat-tab-link\n [active]=\"mode==='mobile'\"\n (click)=\"toggleMode('mobile')\">\n <mat-label>Mobile</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='desktop'\"\n (click)=\"toggleMode('desktop')\">\n <mat-label>Desktop</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='memory'\"\n (click)=\"toggleMode('memory')\">\n <mat-label>Memory leak debug</mat-label>\n </a>\n <a mat-tab-link\n [active]=\"mode==='temp'\"\n (click)=\"toggleMode('temp')\">\n <mat-label>Temporary</mat-label>\n </a>\n </nav>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <!--<ion-grid *ngIf=\"mode === 'temp'\">\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable&lt;any[]&gt;</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n </ion-grid>-->\n\n\n <ion-grid *ngIf=\"mode === 'memory'\">\n\n <!-- debugging memory leak -->\n <ion-row>\n <ion-col>\n <ion-text><h4>Debug memory leak</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"2\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Items type\">\n <mat-select (selectionChange)=\"memoryAutocompleteFieldName=$event.value\" [value]=\"memoryAutocompleteFieldName\">\n <mat-option value=\"entity-$items\">Observable</mat-option>\n <mat-option value=\"entity-suggestFn\">Suggest function</mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n <ion-col size=\"1\" class=\"ion-no-padding\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Mobile ?\">\n <mat-checkbox (change)=\"memoryMobile=$event.checked\" [checked]=\"memoryMobile\">\n </mat-checkbox>\n </mat-form-field>\n </ion-col>\n\n <ion-col size=\"2\">\n <ion-button *ngIf=\"!memoryTimer\" (click)=\"startMemoryTimer()\" color=\"tertiary\">Start</ion-button>\n <ion-button *ngIf=\"memoryTimer\" (click)=\"stopMemoryTimer()\" color=\"tertiary\">Stop</ion-button>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n *ngIf=\"!memoryHide && memoryAutocompleteFieldName\"\n [config]=\"autocompleteFields.get(memoryAutocompleteFieldName)\"\n [mobile]=\"memoryMobile\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-memory-leak]'\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <!-- Mobile mode -->\n <ion-grid *ngIf=\"mode === 'mobile'\">\n\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Entity far in the list (not in first page)\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre style=\"white-space: normal !important;\">value: {{stringify(form.controls.farEntity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"farEntity\" #farEntityField\n [config]=\"autocompleteFields.get('entity-far')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-far]'\"\n [debug]=\"true\"\n [required]=\"true\"\n [clearable]=\"true\"\n placeholder=\"Far entity (in the list)\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, suggestFn: (searchText, filter) =&gt; any[]</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-1]'\"\n [required]=\"true\"\n placeholder=\"Suggest field\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Items is an Observable\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-observable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [clearable]=\"true\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n search with a suggestLengthThreshold\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;\nsuggestLengthThreshold: '3'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-mobile-suggestLengthThreshold]'\"\n required\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"true\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-multiple]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Change filter\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <ion-button (click)=\"updateFilter(filterChangeField, 'entity-items-filter')\">Filter on: {{autocompleteFields.get('entity-items-filter').filter?.searchAttribute }}</ion-button>\n </ion-col>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\" #filterChangeField\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-filter]'\"\n ></mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"min-width-large\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"true\"\n class=\"min-width-large\"\n panelWidth=\"400px\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Fullscreen\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-mobile-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Desktop mode -->\n <ion-grid *ngIf=\"mode === 'desktop'\">\n <ion-row>\n <ion-col>\n <ion-text><h4>Desktop mode</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n items from suggest function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [clearable]=\"true\"\n [logPrefix]=\"'[combo-desktop-suggest]'\">\n </mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n search with a suggestLengthThreshold\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;\nsuggestLengthThreshold: '3'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggestLengthThreshold]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an array\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [logPrefix]=\"'[combo-desktop-array-1]'\"\n [equals]=\"equals\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [equals]=\"equals\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"false\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-multiple]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-missing]'\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size panel\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-disable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"mat-autocomplete-panel-full-size\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n class=\"mat-autocomplete-panel-full-size\"\n panelWidth=\"100vw\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>panelWidth: string</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n panelWidth=\"400px\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n <ion-col size=\"3\">\n <mat-checkbox #showIcons [checked]=\"false\">\n Icons ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n <mat-icon matPrefix *ngIf=\"showIcons.checked\">keyboard_arrow_right</mat-icon>\n <mat-icon matSuffix *ngIf=\"showIcons.checked\">keyboard_arrow_left</mat-icon>\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
31826
+ template: "<ion-header>\n <ion-toolbar color=\"primary\">\n\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Autocomplete field test page</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n\n <!-- Tab nav - mobile/desktop mode -->\n <nav mat-tab-nav-bar>\n <a mat-tab-link\n [active]=\"mode==='mobile'\"\n (click)=\"toggleMode('mobile')\">\n <mat-label>Mobile</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='desktop'\"\n (click)=\"toggleMode('desktop')\">\n <mat-label>Desktop</mat-label>\n </a>\n <a mat-tab-link [active]=\"mode==='memory'\"\n (click)=\"toggleMode('memory')\">\n <mat-label>Memory leak debug</mat-label>\n </a>\n <a mat-tab-link\n [active]=\"mode==='temp'\"\n (click)=\"toggleMode('temp')\">\n <mat-label>Temporary</mat-label>\n </a>\n </nav>\n\n <form class=\"form-container\" [formGroup]=\"form\" (ngSubmit)=\"doSubmit($event)\">\n\n <!--<ion-grid *ngIf=\"mode === 'temp'\">\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>items: Observable&lt;any[]&gt;</pre></small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [compareWith]=\"compareWithFn\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n </ion-row>\n\n\n </ion-grid>-->\n\n\n <ion-grid *ngIf=\"mode === 'memory'\">\n\n <!-- debugging memory leak -->\n <ion-row>\n <ion-col>\n <ion-text><h4>Debug memory leak</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"2\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Items type\">\n <mat-select (selectionChange)=\"memoryAutocompleteFieldName=$event.value\" [value]=\"memoryAutocompleteFieldName\">\n <mat-option value=\"entity-$items\">Observable</mat-option>\n <mat-option value=\"entity-suggestFn\">Suggest function</mat-option>\n </mat-select>\n </mat-form-field>\n </ion-col>\n <ion-col size=\"1\" class=\"ion-no-padding\">\n <mat-form-field floatLabel=\"always\">\n <input matInput type=\"text\" hidden placeholder=\"Mobile ?\">\n <mat-checkbox (change)=\"memoryMobile=$event.checked\" [checked]=\"memoryMobile\">\n </mat-checkbox>\n </mat-form-field>\n </ion-col>\n\n <ion-col size=\"2\">\n <ion-button *ngIf=\"!memoryTimer\" (click)=\"startMemoryTimer()\" color=\"tertiary\">Start</ion-button>\n <ion-button *ngIf=\"memoryTimer\" (click)=\"stopMemoryTimer()\" color=\"tertiary\">Stop</ion-button>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\"\n *ngIf=\"!memoryHide && memoryAutocompleteFieldName\"\n [config]=\"autocompleteFields.get(memoryAutocompleteFieldName)\"\n [mobile]=\"memoryMobile\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-memory-leak]'\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <!-- Mobile mode -->\n <ion-grid *ngIf=\"mode === 'mobile'\">\n\n <ion-row>\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Entity far in the list (not in first page)\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre style=\"white-space: normal !important;\">value: {{stringify(form.controls.farEntity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"farEntity\" #farEntityField\n [config]=\"autocompleteFields.get('entity-far')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-far]'\"\n [debug]=\"true\"\n [required]=\"true\"\n [clearable]=\"true\"\n placeholder=\"Far entity (in the list)\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Suggest() function\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, suggestFn: (searchText, filter) =&gt; any[]</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-suggestFn')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-1]'\"\n [required]=\"true\"\n placeholder=\"Suggest field\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Items is an Observable\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-observable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>mobile: true, items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [clearable]=\"true\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n search with a suggestLengthThreshold\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;\nsuggestLengthThreshold: '3'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-mobile-suggestLengthThreshold]'\"\n required\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"true\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-multiple]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-2]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Change filter\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre></pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col>\n <ion-button (click)=\"updateFilter(filterChangeField, 'entity-items-filter')\">Filter on: {{autocompleteFields.get('entity-items-filter').filter?.searchAttribute }}</ion-button>\n </ion-col>\n <ion-col>\n <mat-autocomplete-field formControlName=\"entity\" #filterChangeField\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-filter]'\"\n ></mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"min-width-large\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"true\"\n class=\"min-width-large\"\n panelWidth=\"400px\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-mobile-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Fullscreen\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"true\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-mobile-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n </ion-grid>\n\n <!-- Desktop mode -->\n <ion-grid *ngIf=\"mode === 'desktop'\">\n <ion-row>\n <ion-col>\n <ion-text><h4>Desktop mode</h4></ion-text>\n </ion-col>\n </ion-row>\n <ion-row>\n\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n items from suggest function\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [clearable]=\"true\"\n [logPrefix]=\"'[combo-desktop-suggest]'\"\n [debug]=\"true\">\n </mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n search with a suggestLengthThreshold\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>suggest: (value, filter) => LoadResult&lt;any&gt;\nsuggestLengthThreshold: '3'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n suggestLengthThreshold=\"3\"\n [logPrefix]=\"'[combo-desktop-suggestLengthThreshold]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an array\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: [], value: {{stringify(form.controls.entity.value)}}</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items')\"\n [logPrefix]=\"'[combo-desktop-array-1]'\"\n [equals]=\"equals\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Items is an Observable\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [logPrefix]=\"'[combo-desktop-2]'\"\n [equals]=\"equals\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Multiple value\n </ion-text>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small><pre>multiple: true</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entities\"\n [config]=\"autocompleteFields.get('entities-items-filter')\"\n [placeholder]=\"'Multiple'\"\n mobile=\"false\"\n multiple=\"true\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-multiple]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Control value if missing in items\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>items: Observable&lt;any[]&gt;</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"missingEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-missing]'\"\n [mobile]=\"false\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size panel\n </ion-label>\n </ion-card-title>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class: 'mat-autocomplete-panel-full-size'</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [class]=\"'mat-autocomplete-panel-full-size'\"\n [matAutocompletePosition]=\"'above'\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n [debug]=\"true\"\n [showAllOnFocus]=\"true\"\n [showPanelOnFocus]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Disabled control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"disableEntity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-disable]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col>\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Readonly control\n </ion-label>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-$items')\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n <ion-row>\n <ion-col size=\"9\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Full size combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>class=\"mat-autocomplete-panel-full-size\"</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n class=\"mat-autocomplete-panel-full-size\"\n panelWidth=\"100vw\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-full-size]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"3\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-label color=\"primary\">\n Large combo\n </ion-label>\n <ion-card-subtitle>\n <ion-text color=\"medium\">\n <small>\n <pre>panelWidth: string</pre>\n </small>\n </ion-text>\n </ion-card-subtitle>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <mat-autocomplete-field formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-large')\"\n [mobile]=\"false\"\n panelWidth=\"400px\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-large]'\"\n ></mat-autocomplete-field>\n </ion-card-content>\n </ion-card>\n </ion-col>\n\n <ion-col size=\"6\">\n <ion-card>\n <ion-card-header>\n <ion-card-title>\n <ion-text color=\"primary\">\n Readonly toggle\n </ion-text>\n </ion-card-title>\n </ion-card-header>\n <ion-card-content>\n <ion-grid>\n <ion-row>\n <ion-col size=\"3\">\n <mat-checkbox (change)=\"readonlyField.readonly=$event.checked\" [checked]=\"readonlyField.readonly\">\n Readonly ?\n </mat-checkbox>\n </ion-col>\n <ion-col size=\"3\">\n <mat-checkbox #showIcons [checked]=\"false\">\n Icons ?\n </mat-checkbox>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <mat-autocomplete-field #readonlyField formControlName=\"entity\"\n [config]=\"autocompleteFields.get('entity-items-filter')\"\n [placeholder]=\"'Entity'\"\n [mobile]=\"false\"\n [equals]=\"equals\"\n [logPrefix]=\"'[combo-desktop-readonly]'\"\n [readonly]=\"true\"\n [clearable]=\"!readonlyField.readonly\">\n <mat-icon matPrefix *ngIf=\"showIcons.checked\">keyboard_arrow_right</mat-icon>\n <mat-icon matSuffix *ngIf=\"showIcons.checked\">keyboard_arrow_left</mat-icon>\n </mat-autocomplete-field>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-card-content>\n </ion-card>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n </form>\n\n</ion-content>\n"
32471
31827
  },] }
32472
31828
  ];
32473
31829
  AutocompleteTestPage.ctorParameters = function () { return [
@@ -32549,13 +31905,13 @@
32549
31905
  { type: i1.FormBuilder }
32550
31906
  ]; };
32551
31907
 
32552
- var moment$7 = momentImported__namespace;
31908
+ var moment$6 = momentImported__namespace;
32553
31909
  var SwipeTestPage = /** @class */ (function () {
32554
31910
  function SwipeTestPage(formBuilder, dateFormatPipe) {
32555
31911
  this.formBuilder = formBuilder;
32556
31912
  this.dateFormatPipe = dateFormatPipe;
32557
31913
  this.$dates = new rxjs.BehaviorSubject(undefined);
32558
- this._today = moment$7().startOf('day');
31914
+ this._today = moment$6().startOf('day');
32559
31915
  this.form = formBuilder.group({
32560
31916
  empty: [null, i1.Validators.required],
32561
31917
  date: [null, i1.Validators.compose([i1.Validators.required, SharedValidators.validDate])],
@@ -32569,7 +31925,7 @@
32569
31925
  var _this = this;
32570
31926
  var dates = [];
32571
31927
  for (var d = 0; d < 7; d++) {
32572
- dates[d] = moment$7(this._today).add(d - 3, 'day');
31928
+ dates[d] = moment$6(this._today).add(d - 3, 'day');
32573
31929
  }
32574
31930
  this.$dates.next(dates);
32575
31931
  this.loadData();
@@ -32616,7 +31972,7 @@
32616
31972
  { type: DateFormatPipe }
32617
31973
  ]; };
32618
31974
 
32619
- var moment$8 = momentImported__namespace;
31975
+ var moment$7 = momentImported__namespace;
32620
31976
  var DateTimeTestPage = /** @class */ (function () {
32621
31977
  function DateTimeTestPage(platform, formBuilder, cd) {
32622
31978
  this.platform = platform;
@@ -32652,7 +32008,7 @@
32652
32008
  var now, data;
32653
32009
  var _this = this;
32654
32010
  return __generator(this, function (_a) {
32655
- now = moment$8();
32011
+ now = moment$7();
32656
32012
  data = {
32657
32013
  empty: null,
32658
32014
  emptyRequired: null,
@@ -32930,7 +32286,7 @@
32930
32286
  { type: i1.FormBuilder }
32931
32287
  ]; };
32932
32288
 
32933
- var moment$9 = momentImported__namespace;
32289
+ var moment$8 = momentImported__namespace;
32934
32290
  var DateTestPage = /** @class */ (function () {
32935
32291
  function DateTestPage(formBuilder, cd) {
32936
32292
  this.formBuilder = formBuilder;
@@ -32967,7 +32323,7 @@
32967
32323
  var now, nowAtMahe, data;
32968
32324
  var _this = this;
32969
32325
  return __generator(this, function (_a) {
32970
- now = moment$9();
32326
+ now = moment$8();
32971
32327
  nowAtMahe = now.clone().tz(this.timezone).startOf('day');
32972
32328
  data = {
32973
32329
  empty: null,
@@ -33806,7 +33162,6 @@
33806
33162
  exports.APP_MENU_ITEMS = APP_MENU_ITEMS;
33807
33163
  exports.APP_TESTING_PAGES = APP_TESTING_PAGES;
33808
33164
  exports.AboutModal = AboutModal;
33809
- exports.AbstractUserEventService = AbstractUserEventService;
33810
33165
  exports.AccountPage = AccountPage;
33811
33166
  exports.AccountService = AccountService;
33812
33167
  exports.AccountToStringPipe = AccountToStringPipe;
@@ -33933,11 +33288,6 @@
33933
33288
  exports.IsNotNilOrBlankPipe = IsNotNilOrBlankPipe;
33934
33289
  exports.IsNotOnFieldModePipe = IsNotOnFieldModePipe;
33935
33290
  exports.IsOnFieldModePipe = IsOnFieldModePipe;
33936
- exports.Job = Job;
33937
- exports.JobModule = JobModule;
33938
- exports.JobProgressionComponent = JobProgressionComponent;
33939
- exports.JobProgressionService = JobProgressionService;
33940
- exports.JobProgressionServiceToken = JobProgressionServiceToken;
33941
33291
  exports.JobUtils = JobUtils;
33942
33292
  exports.KEYBOARD_HIDE_DELAY_MS = KEYBOARD_HIDE_DELAY_MS;
33943
33293
  exports.LAT_LONG_DEFAULT_MAX_DECIMALS = LAT_LONG_DEFAULT_MAX_DECIMALS;
@@ -33975,7 +33325,6 @@
33975
33325
  exports.MenuService = MenuService;
33976
33326
  exports.MessageForm = MessageForm;
33977
33327
  exports.MessageModal = MessageModal;
33978
- exports.MessageModule = MessageModule;
33979
33328
  exports.MessageService = MessageService;
33980
33329
  exports.MessageTypeList = MessageTypeList;
33981
33330
  exports.MessageTypes = MessageTypes;
@@ -34043,7 +33392,6 @@
34043
33392
  exports.SharedValidators = SharedValidators;
34044
33393
  exports.SocialErrorCodes = SocialErrorCodes;
34045
33394
  exports.SocialModule = SocialModule;
34046
- exports.SocialModuleOptionsToken = SocialModuleOptionsToken;
34047
33395
  exports.StartableService = StartableService;
34048
33396
  exports.StatusById = StatusById;
34049
33397
  exports.StatusIds = StatusIds;
@@ -34072,10 +33420,7 @@
34072
33420
  exports.UploadFileTestingPage = UploadFileTestingPage;
34073
33421
  exports.UriUtils = UriUtils;
34074
33422
  exports.UserEventFragments = UserEventFragments;
34075
- exports.UserEventModule = UserEventModule;
34076
- exports.UserEventNotificationComponent = UserEventNotificationComponent;
34077
33423
  exports.UserEventService = UserEventService;
34078
- exports.UserEventServiceToken = UserEventServiceToken;
34079
33424
  exports.UserEventTypes = UserEventTypes;
34080
33425
  exports.UserEventsTable = UserEventsTable;
34081
33426
  exports.UsersPage = UsersPage;
@@ -34226,6 +33571,7 @@
34226
33571
  exports.uncapitalizeFirstLetter = uncapitalizeFirstLetter;
34227
33572
  exports.updateValueAndValidity = updateValueAndValidity;
34228
33573
  exports.waitFor = waitFor;
33574
+ exports.waitForFalse = waitForFalse;
34229
33575
  exports.waitForTrue = waitForTrue;
34230
33576
  exports.waitIdle = waitIdle;
34231
33577
  exports.waitWhilePending = waitWhilePending;
@@ -34240,13 +33586,11 @@
34240
33586
  exports.ɵh = LocalSettingsValidatorService;
34241
33587
  exports.ɵi = AppUpdateOfflineModeCard;
34242
33588
  exports.ɵj = AppIconComponent;
34243
- exports.ɵk = UserEventNotificationList;
34244
- exports.ɵl = JobProgressionList;
34245
- exports.ɵm = DateTestPage;
34246
- exports.ɵn = NumpadTestPage;
34247
- exports.ɵo = MatBadgeIconTestPage;
34248
- exports.ɵp = ToastTestingModule;
34249
- exports.ɵq = ToastTestingPage;
33589
+ exports.ɵk = DateTestPage;
33590
+ exports.ɵl = NumpadTestPage;
33591
+ exports.ɵm = MatBadgeIconTestPage;
33592
+ exports.ɵn = ToastTestingModule;
33593
+ exports.ɵo = ToastTestingPage;
34250
33594
 
34251
33595
  Object.defineProperty(exports, '__esModule', { value: true });
34252
33596