@sumaris-net/ngx-components 1.22.11-rc9 → 1.22.11

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 (42) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +538 -355
  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/esm2015/public_api.js +2 -2
  6. package/esm2015/src/app/admin/users/list/users.js +2 -3
  7. package/esm2015/src/app/core/form/entity-editor-modal.class.js +3 -2
  8. package/esm2015/src/app/core/form/entity-editor.class.js +5 -4
  9. package/esm2015/src/app/core/menu/menu.component.js +1 -1
  10. package/esm2015/src/app/core/services/account.service.js +2 -2
  11. package/esm2015/src/app/core/services/model/person.model.js +4 -2
  12. package/esm2015/src/app/shared/file/file.service.js +18 -18
  13. package/esm2015/src/app/shared/file/file.utils.js +1 -1
  14. package/esm2015/src/app/shared/file/images.utils.js +166 -0
  15. package/esm2015/src/app/social/job/progression/job-progression.list.js +1 -1
  16. package/esm2015/src/app/social/user-event/notification/user-event-notification.icon.js +7 -6
  17. package/esm2015/src/app/social/user-event/notification/user-event-notification.list.js +48 -24
  18. package/esm2015/src/app/social/user-event/testing/user-event.testing.js +61 -10
  19. package/esm2015/src/app/social/user-event/testing/user-event.testing.model.js +103 -0
  20. package/esm2015/src/app/social/user-event/testing/user-event.testing.service.js +40 -31
  21. package/esm2015/src/app/social/user-event/user-event.model.js +2 -106
  22. package/esm2015/src/app/social/user-event/user-event.module.js +4 -2
  23. package/esm2015/src/app/social/user-event/user-event.service.js +65 -49
  24. package/fesm2015/sumaris-net.ngx-components.js +407 -313
  25. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  26. package/package.json +1 -1
  27. package/public_api.d.ts +1 -1
  28. package/src/app/admin/users/list/users.d.ts +0 -2
  29. package/src/app/core/form/entity-editor.class.d.ts +1 -1
  30. package/src/app/shared/file/file.service.d.ts +5 -5
  31. package/src/app/shared/file/images.utils.d.ts +19 -0
  32. package/src/app/social/user-event/notification/user-event-notification.list.d.ts +18 -14
  33. package/src/app/social/user-event/testing/user-event.testing.d.ts +11 -3
  34. package/src/app/social/user-event/testing/user-event.testing.model.d.ts +41 -0
  35. package/src/app/social/user-event/testing/user-event.testing.service.d.ts +7 -6
  36. package/src/app/social/user-event/user-event.model.d.ts +10 -44
  37. package/src/app/social/user-event/user-event.service.d.ts +9 -8
  38. package/sumaris-net.ngx-components.metadata.json +1 -1
  39. package/esm2015/src/app/shared/file/base64-image-reader.js +0 -141
  40. package/esm2015/src/app/social/user-event/user-event.fragments.js +0 -27
  41. package/src/app/shared/file/base64-image-reader.d.ts +0 -18
  42. package/src/app/social/user-event/user-event.fragments.d.ts +0 -4
@@ -48,7 +48,7 @@ import { MatTooltipModule } from '@angular/material/tooltip';
48
48
  import { MatChipsModule } from '@angular/material/chips';
49
49
  import { ActivatedRoute, Router, RouterModule, RouteReuseStrategy } from '@angular/router';
50
50
  import { HammerGestureConfig, EventManager } from '@angular/platform-browser';
51
- import { HttpResponse, HttpClient, HttpHeaders, HttpEventType, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
51
+ import { HttpResponse, HttpEventType, HttpClient, HttpHeaders, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
52
52
  import { ColorPickerModule } from 'ngx-color-picker';
53
53
  import { NativeAudio as NativeAudio$1 } from '@ionic-native/native-audio/ngx';
54
54
  import { Vibration as Vibration$1 } from '@ionic-native/vibration/ngx';
@@ -57,6 +57,7 @@ import { NativeAudio } from '@ionic-native/native-audio/ngx/index';
57
57
  import { Vibration } from '@ionic-native/vibration/ngx/index';
58
58
  import { AudioManagement as AudioManagement$1 } from '@ionic-native/audio-management/ngx/index';
59
59
  import * as uuidv4Imported from 'uuid/v4';
60
+ import { mergeMap as mergeMap$1 } from 'rxjs/internal/operators';
60
61
  import { DragDropModule } from '@angular/cdk/drag-drop';
61
62
  import { MarkdownModule } from 'ngx-markdown';
62
63
  import { sign, box, hash, verify } from 'tweetnacl';
@@ -9397,31 +9398,77 @@ SharedHotkeysModule.decorators = [
9397
9398
  },] }
9398
9399
  ];
9399
9400
 
9401
+ class UploadFile extends File {
9402
+ }
9403
+ class FileResponse {
9404
+ constructor(init) {
9405
+ this.type = HttpEventType.Response;
9406
+ this.body = isNotNil(init === null || init === void 0 ? void 0 : init.body) ? init.body : null;
9407
+ this.status = (init === null || init === void 0 ? void 0 : init.status) || 0;
9408
+ this.statusText = (init === null || init === void 0 ? void 0 : init.statusText) || 'OK';
9409
+ }
9410
+ }
9411
+ function isProgressEvent(event) {
9412
+ return event && (event.type === HttpEventType.UploadProgress
9413
+ || event.type === HttpEventType.DownloadProgress);
9414
+ }
9415
+ function isResponseEvent(event) {
9416
+ return event && event.type === HttpEventType.Response;
9417
+ }
9418
+
9400
9419
  const IMAGE_DEFAULTS = {
9401
9420
  MAX_HEIGHT: 480,
9402
9421
  MAX_WIDTH: 640,
9403
9422
  THUMB_MAX_HEIGHT: 200,
9404
9423
  THUMB_MAX_WIDTH: 200
9405
9424
  };
9406
- class Base64ImageReader {
9407
- constructor() {
9408
- }
9409
- readFromBlob(file) {
9410
- return __awaiter(this, void 0, void 0, function* () {
9411
- if (!file)
9412
- throw new Error('Illegal argument: missing file');
9413
- const dataUrl = yield new Promise((resolve, reject) => {
9414
- const reader = new FileReader();
9415
- reader.addEventListener('load', (event) => resolve(reader.result), false);
9416
- reader.readAsDataURL(file);
9417
- });
9418
- return dataUrl;
9419
- });
9425
+ // @dynamic
9426
+ class ImagesUtils {
9427
+ static readAsDataURL(file, opts) {
9428
+ const $progress = new Subject();
9429
+ const reader = new FileReader();
9430
+ // Listen progress
9431
+ reader.onprogress = (e) => {
9432
+ const total = e.total || 1;
9433
+ const loaded = e.total || 0;
9434
+ if (loaded < total)
9435
+ $progress.next({ type: HttpEventType.UploadProgress, loaded, total });
9436
+ };
9437
+ // Listen end
9438
+ reader.onloadend = (e) => {
9439
+ const body = reader.result;
9440
+ if (typeof body === 'string') {
9441
+ $progress.next(new FileResponse({ body }));
9442
+ $progress.complete();
9443
+ }
9444
+ else {
9445
+ console.error(`[image-utils] Cannot read file '${file.name}' as text`);
9446
+ $progress.error(`Cannot read file as text`);
9447
+ }
9448
+ };
9449
+ // Listen error
9450
+ reader.onerror = (event) => {
9451
+ console.error('[image-utils] Error while reading file:', event);
9452
+ $progress.error(event);
9453
+ };
9454
+ // Start reading the file
9455
+ reader.readAsDataURL(file);
9456
+ // Resize image, if need
9457
+ if (opts) {
9458
+ return $progress.pipe(mergeMap$1((event) => __awaiter(this, void 0, void 0, function* () {
9459
+ if (event instanceof FileResponse) {
9460
+ const body = yield ImagesUtils.resizeBase64(event.body, opts);
9461
+ return new FileResponse({ body });
9462
+ }
9463
+ return event;
9464
+ })));
9465
+ }
9466
+ return $progress.asObservable();
9420
9467
  }
9421
- readAndResizeFromUrl(path, opts) {
9468
+ static readAndResizeFromUrl(fileUrl, opts) {
9422
9469
  return __awaiter(this, void 0, void 0, function* () {
9423
- if (isNilOrBlank(path))
9424
- throw new Error('Illegal argument: missing path');
9470
+ if (isNilOrBlank(fileUrl))
9471
+ throw new Error('Illegal argument: missing fileUrl');
9425
9472
  // Create the temporary image element
9426
9473
  const img = document.createElement('img');
9427
9474
  // Need to avoid CORS error
@@ -9429,23 +9476,21 @@ class Base64ImageReader {
9429
9476
  img.crossOrigin = 'anonymous';
9430
9477
  try {
9431
9478
  return yield new Promise((resolve, reject) => {
9432
- img.addEventListener('load', this.createImageOnLoadResizeFn(resolve, reject, opts), false);
9479
+ img.addEventListener('load', ImagesUtils.createImageOnLoadResizeFn(resolve, reject, opts), false);
9433
9480
  img.addEventListener('error', reject);
9434
- img.src = path;
9481
+ img.src = fileUrl;
9435
9482
  });
9436
9483
  }
9437
9484
  catch (err) {
9438
- throw new Error(`Failed to load and resize image {${path}}`);
9485
+ throw new Error(`Failed to load and resize image {${fileUrl}}`);
9439
9486
  }
9440
9487
  finally {
9441
9488
  img.remove();
9442
9489
  }
9443
9490
  });
9444
9491
  }
9445
- readAndResizeFromBlob(file, opts) {
9492
+ static resizeBase64(dataUrl, opts) {
9446
9493
  return __awaiter(this, void 0, void 0, function* () {
9447
- if (!file)
9448
- throw new Error('Illegal argument: missing file');
9449
9494
  // Create the temporary image element
9450
9495
  const img = document.createElement('img');
9451
9496
  // Need to avoid CORS error
@@ -9453,13 +9498,9 @@ class Base64ImageReader {
9453
9498
  img.crossOrigin = 'anonymous';
9454
9499
  try {
9455
9500
  return yield new Promise((resolve, reject) => {
9456
- const reader = new FileReader();
9457
- reader.addEventListener('load', (event) => {
9458
- // Resize image
9459
- img.onload = this.createImageOnLoadResizeFn(resolve, reject, opts);
9460
- img.src = reader.result;
9461
- }, false);
9462
- reader.readAsDataURL(file);
9501
+ img.addEventListener('load', ImagesUtils.createImageOnLoadResizeFn(resolve, reject, opts), false);
9502
+ img.addEventListener('error', reject);
9503
+ img.src = dataUrl;
9463
9504
  });
9464
9505
  }
9465
9506
  finally {
@@ -9467,8 +9508,7 @@ class Base64ImageReader {
9467
9508
  }
9468
9509
  });
9469
9510
  }
9470
- /* -- protected methods -- */
9471
- createImageOnLoadResizeFn(resolve, reject, opts) {
9511
+ static createImageOnLoadResizeFn(resolve, reject, opts) {
9472
9512
  return function (event) {
9473
9513
  const maxWidth = (opts && opts.thumbnail ? IMAGE_DEFAULTS.THUMB_MAX_WIDTH : (opts && opts.maxWidth || IMAGE_DEFAULTS.MAX_WIDTH));
9474
9514
  const maxHeight = (opts && opts.thumbnail ? IMAGE_DEFAULTS.THUMB_MAX_HEIGHT : (opts && opts.maxHeight || IMAGE_DEFAULTS.MAX_HEIGHT));
@@ -9562,24 +9602,24 @@ class FileService {
9562
9602
  const jobsFactories = (sources || []).map(source => () => this.getImage(source, Object.assign({}, opts)));
9563
9603
  return chainPromises(jobsFactories);
9564
9604
  }
9565
- getImage(source, opts) {
9605
+ getImage(fileUrl, opts) {
9566
9606
  return __awaiter(this, void 0, void 0, function* () {
9567
- let responseType = opts && opts.responseType || (this.canUseFileSystem ? 'file' : 'dataUrl');
9607
+ let outputType = opts && opts.outputType || (this.canUseFileSystem ? 'fileUrl' : 'dataUrl');
9568
9608
  const debug = this._debug /*&& (!opts || !opts.fileTransfer)*/;
9569
9609
  const now = debug && Date.now();
9570
9610
  if (debug)
9571
- console.debug(`[file] Fetching image {${source}} into ${responseType}...`);
9611
+ console.debug(`[file] Fetching image {${fileUrl}} into ${outputType}...`);
9572
9612
  // Read the filename
9573
- const lastSlashIndex = source.lastIndexOf('/');
9613
+ const lastSlashIndex = fileUrl.lastIndexOf('/');
9574
9614
  if (lastSlashIndex === -1)
9575
- throw new Error('Invalid URL: ' + source);
9576
- const fileName = lastSlashIndex < (source.length - 1) && source.substring(lastSlashIndex + 1) || uuidv4();
9615
+ throw new Error('Invalid URL: ' + fileUrl);
9616
+ const fileName = lastSlashIndex < (fileUrl.length - 1) && fileUrl.substring(lastSlashIndex + 1) || uuidv4();
9577
9617
  // Download into the file system
9578
- if (responseType === 'file' && this.canUseFileSystem) {
9579
- console.warn(`WARN: [file] Fetching image {${source}} in local file...`);
9618
+ if (outputType === 'fileUrl' && this.canUseFileSystem) {
9619
+ console.warn(`WARN: [file] Downloading image {${fileUrl}} in local filesystem...`);
9580
9620
  const targetFilePath = this._imageDirectory + fileName;
9581
9621
  try {
9582
- const blob = yield firstNotNilPromise(this.http.get(source, {
9622
+ const blob = yield firstNotNilPromise(this.http.get(fileUrl, {
9583
9623
  observe: 'body',
9584
9624
  responseType: 'blob',
9585
9625
  reportProgress: false
@@ -9589,24 +9629,24 @@ class FileService {
9589
9629
  //const fileTransfer = (opts && opts.fileTransfer) || this.transfer.create();
9590
9630
  //await fileTransfer.download(source, targetFilePath);
9591
9631
  if (debug)
9592
- console.debug(`[file] Fetching image {${source}} into ${responseType} [OK] in ${Date.now() - now}ms`);
9632
+ console.debug(`[file] Fetching image {${fileUrl}} into ${outputType} [OK] in ${Date.now() - now}ms`);
9593
9633
  return targetFilePath;
9594
9634
  }
9595
9635
  catch (err) {
9596
- console.error(`[file] Error while download ${source}: ${err && err.message || err}`);
9636
+ console.error(`[file] Error while download ${fileUrl}: ${err && err.message || err}`);
9597
9637
  // Continue (fallback to data Url)
9598
- responseType = 'dataUrl';
9638
+ outputType = 'dataUrl';
9599
9639
  }
9600
9640
  }
9601
- if (responseType === 'dataUrl') {
9641
+ if (outputType === 'dataUrl') {
9602
9642
  // Get as data url (e.g. 'data:image/png:...')
9603
- const dataUrl = yield new Base64ImageReader().readAndResizeFromUrl(source, opts);
9643
+ const dataUrl = yield ImagesUtils.readAndResizeFromUrl(fileUrl, opts);
9604
9644
  if (debug)
9605
- console.debug(`[file] Fetching image {${source}} into ${responseType} [OK] in ${Date.now() - now}ms`);
9645
+ console.debug(`[file] Fetching image {${fileUrl}} into ${outputType} [OK] in ${Date.now() - now}ms`);
9606
9646
  return dataUrl;
9607
9647
  }
9608
9648
  // Keep original URL
9609
- return source;
9649
+ return fileUrl;
9610
9650
  });
9611
9651
  }
9612
9652
  /* -- protected methods -- */
@@ -13122,7 +13162,9 @@ class PersonUtils {
13122
13162
  return expectedProfileIndex !== -1 && PersonUtils.getMainProfileIndex(actualProfiles) <= expectedProfileIndex;
13123
13163
  }
13124
13164
  static personToString(obj) {
13125
- return obj && obj.id && (obj.lastName + ' ' + obj.firstName) || undefined;
13165
+ if (!obj || !obj.id)
13166
+ return undefined;
13167
+ return obj.lastName + ' ' + obj.firstName;
13126
13168
  }
13127
13169
  static personsToString(data, separator) {
13128
13170
  return (data || []).map(PersonUtils.personToString).join(separator || ', ');
@@ -15044,7 +15086,7 @@ class AccountService extends BaseGraphqlService {
15044
15086
  if (hasAvatarUrl && this.network.online) {
15045
15087
  yield this.file.getImage(json.avatar, {
15046
15088
  thumbnail: true,
15047
- responseType: 'dataUrl'
15089
+ outputType: 'dataUrl'
15048
15090
  })
15049
15091
  .then(dataUrl => {
15050
15092
  if (dataUrl && this._debug)
@@ -15922,24 +15964,6 @@ ConfigService.ctorParameters = () => [
15922
15964
  { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [APP_CONFIG_OPTIONS,] }] }
15923
15965
  ];
15924
15966
 
15925
- class UploadFile extends File {
15926
- }
15927
- class FileResponse {
15928
- constructor(init) {
15929
- this.type = HttpEventType.Response;
15930
- this.body = isNotNil(init === null || init === void 0 ? void 0 : init.body) ? init.body : null;
15931
- this.status = (init === null || init === void 0 ? void 0 : init.status) || 0;
15932
- this.statusText = (init === null || init === void 0 ? void 0 : init.statusText) || 'OK';
15933
- }
15934
- }
15935
- function isProgressEvent(event) {
15936
- return event && (event.type === HttpEventType.UploadProgress
15937
- || event.type === HttpEventType.DownloadProgress);
15938
- }
15939
- function isResponseEvent(event) {
15940
- return event && event.type === HttpEventType.Response;
15941
- }
15942
-
15943
15967
  class UploadFilePopover {
15944
15968
  constructor(popoverController, translate, cd) {
15945
15969
  this.popoverController = popoverController;
@@ -21493,7 +21517,7 @@ MenuComponent.decorators = [
21493
21517
  template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" [contentId]=\"contentId\">\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 [title]=\"'MENU.BTN_MY_ACCOUNT'|translate\">\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\" style=\"width: 108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n <ion-col>\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\"\n [title]=\"'MENU.BTN_MY_ACCOUNT'|translate\">\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 </ion-col>\n\n <!-- Insertion headerBottomRight -->\n <ion-col size=\"auto\">\n <ng-container *ngTemplateOutlet=\"headerBottomRight\"></ng-container>\n </ion-col>\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\n<ng-template #headerBottomRight>\n <ng-content select=\"[headerBottomRight]\"></ng-content>\n</ng-template>\n",
21494
21518
  animations: [fadeInAnimation],
21495
21519
  changeDetection: ChangeDetectionStrategy.OnPush,
21496
- 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-avatar:hover{background-color:var(--ion-color-secondary-shade);border:2px solid var(--ion-color-primary-shade)}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)}}"]
21520
+ 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 rgba(var(--ion-color-secondary-rgb),.5);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-avatar:hover{background-color:var(--ion-color-secondary-shade);border:2px solid var(--ion-color-secondary-shade)}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)}}"]
21497
21521
  },] }
21498
21522
  ];
21499
21523
  MenuComponent.ctorParameters = () => [
@@ -24834,10 +24858,10 @@ class AppEntityEditor extends AppTabEditor {
24834
24858
  this.savingSubject = new BehaviorSubject(false);
24835
24859
  this.$title = new Subject();
24836
24860
  this.onUpdateView = new EventEmitter();
24837
- this.environement = injector.get(ENVIRONMENT);
24861
+ this.environment = injector.get(ENVIRONMENT);
24838
24862
  options = Object.assign({
24839
24863
  // Default options
24840
- enableListenChanges: ((_a = this.environement.entityEditor) === null || _a === void 0 ? void 0 : _a.enableListenChanges) || false, listenIntervalInSeconds: toNumber((_b = this.environement.entityEditor) === null || _b === void 0 ? void 0 : _b.listenIntervalInSeconds, 0), pathIdAttribute: 'id', autoLoad: true, autoUpdateRoute: true, i18nPrefix: '' }, options);
24864
+ enableListenChanges: ((_a = this.environment.entityEditor) === null || _a === void 0 ? void 0 : _a.enableListenChanges) || false, listenIntervalInSeconds: toNumber((_b = this.environment.entityEditor) === null || _b === void 0 ? void 0 : _b.listenIntervalInSeconds, 0), pathIdAttribute: 'id', autoLoad: true, autoUpdateRoute: true, i18nPrefix: '' }, options);
24841
24865
  this.settings = injector.get(LocalSettingsService);
24842
24866
  this.errorTranslator = injector.get(FormErrorTranslator);
24843
24867
  this.cd = injector.get(ChangeDetectorRef);
@@ -25077,13 +25101,14 @@ class AppEntityEditor extends AppTabEditor {
25077
25101
  * Enable or disable state
25078
25102
  */
25079
25103
  updateViewState(data, opts) {
25104
+ var _a;
25080
25105
  if (this.isNewData || this.canUserWrite(data)) {
25081
25106
  this.enable(opts);
25082
25107
  }
25083
25108
  else {
25084
25109
  this.disable(opts);
25085
25110
  // Allow to sort table
25086
- this.tables.forEach(t => t.enableSort());
25111
+ (_a = this.tables) === null || _a === void 0 ? void 0 : _a.forEach(t => t.enableSort());
25087
25112
  }
25088
25113
  }
25089
25114
  /**
@@ -25645,13 +25670,14 @@ class AppEntityEditorModal extends AppTabEditor {
25645
25670
  * Enable or disable state
25646
25671
  */
25647
25672
  updateViewState(data, opts) {
25673
+ var _a;
25648
25674
  if (this.isNewData || this.enabled) {
25649
25675
  this.enable(opts);
25650
25676
  }
25651
25677
  else {
25652
25678
  this.disable(opts);
25653
25679
  // Allow to sort table
25654
- this.tables.forEach(t => t.enableSort());
25680
+ (_a = this.tables) === null || _a === void 0 ? void 0 : _a.forEach(t => t.enableSort());
25655
25681
  }
25656
25682
  }
25657
25683
  saveAndClose(event) {
@@ -26039,13 +26065,13 @@ class AbstractUserEventService extends BaseGraphqlService {
26039
26065
  fetchPolicy: (opts === null || opts === void 0 ? void 0 : opts.fetchPolicy) || 'cache-first',
26040
26066
  insertFilterFn: filter && filter.asFilterFn()
26041
26067
  })
26042
- .pipe(map(res => {
26043
- let data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this));
26068
+ .pipe(mergeMap((res) => __awaiter(this, void 0, void 0, function* () {
26069
+ let data = yield Promise.all(((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this)));
26044
26070
  if (now) {
26045
26071
  console.debug(`${this._logPrefix}${data.length} user events loaded in ${Date.now() - now}ms`);
26046
26072
  now = null;
26047
26073
  }
26048
- // Must re-order because of listenChanges result will add new event at the end
26074
+ // Must re-order because of listenAllChanges result will add new event at the end
26049
26075
  data = EntityUtils.sort(data, page.sortBy, page.sortDirection);
26050
26076
  const result = {
26051
26077
  data,
@@ -26059,7 +26085,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26059
26085
  }
26060
26086
  }
26061
26087
  return result;
26062
- }));
26088
+ })));
26063
26089
  }
26064
26090
  loadPage(page, filter, opts) {
26065
26091
  var _a;
@@ -26089,10 +26115,10 @@ class AbstractUserEventService extends BaseGraphqlService {
26089
26115
  error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
26090
26116
  fetchPolicy: opts === null || opts === void 0 ? void 0 : opts.fetchPolicy
26091
26117
  });
26092
- let data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this));
26118
+ let data = yield Promise.all(((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this)));
26093
26119
  if (now)
26094
26120
  console.debug(`${this._logPrefix}${data.length} user events loaded in ${Date.now() - now}ms`);
26095
- // Must re-order because of listenChanges result will add new event at the end
26121
+ // Must re-order because of listenAllChanges result will add new event at the end
26096
26122
  data = EntityUtils.sort(data, page.sortBy, page.sortDirection);
26097
26123
  const result = {
26098
26124
  data,
@@ -26109,16 +26135,20 @@ class AbstractUserEventService extends BaseGraphqlService {
26109
26135
  });
26110
26136
  }
26111
26137
  add(entity) {
26112
- // TODO set an id !!!!!!!!!!!!!!!!!!!!!!!!!
26113
- entity = this.processUserEvent(entity);
26114
- const withContent = !!entity.content;
26115
- // Add user event locally
26116
- this.insertIntoMutableCachedQueries(this.graphql.cache, {
26117
- query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26118
- data: entity
26138
+ return __awaiter(this, void 0, void 0, function* () {
26139
+ // TODO set an id !!!!!!!!!!!!!!!!!!!!!!!!!
26140
+ entity = yield this.processUserEvent(entity);
26141
+ if (!entity)
26142
+ return; // Rejected
26143
+ const withContent = !!entity.content;
26144
+ // Add user event locally
26145
+ this.insertIntoMutableCachedQueries(this.graphql.cache, {
26146
+ query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26147
+ data: entity
26148
+ });
26149
+ // Update count
26150
+ this._countSubject.next(this._countSubject.value + 1);
26119
26151
  });
26120
- // Update count
26121
- this._countSubject.next(this._countSubject.value + 1);
26122
26152
  }
26123
26153
  count(filter, options) {
26124
26154
  var _a;
@@ -26175,37 +26205,44 @@ class AbstractUserEventService extends BaseGraphqlService {
26175
26205
  return total;
26176
26206
  }));
26177
26207
  }
26178
- listenChanges(filter, options) {
26208
+ listenAllChanges(filter, opts) {
26179
26209
  var _a;
26180
- if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenChanges)) {
26181
- console.warn(`${this._logPrefix}Subscription query 'listenChanges' not provided, skip.`);
26210
+ if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenAllChanges)) {
26211
+ console.warn(`${this._logPrefix}Subscription query 'listenAllChanges' not provided, skip.`);
26182
26212
  return of();
26183
26213
  }
26184
26214
  if (!filter)
26185
26215
  filter = this.defaultFilter();
26186
26216
  filter = this.asFilter(filter);
26187
- const withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
26217
+ const withContent = (opts === null || opts === void 0 ? void 0 : opts.withContent) === true;
26188
26218
  if (this._debug)
26189
26219
  console.debug(`${this._logPrefix}[WS] Listening changes for user events with filter:`, filter);
26190
26220
  return this.graphql.subscribe({
26191
- query: this.subscriptions.listenChanges,
26192
- fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
26193
- variables: { filter: filter.asPodObject(), interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
26221
+ query: this.subscriptions.listenAllChanges,
26222
+ fetchPolicy: opts === null || opts === void 0 ? void 0 : opts.fetchPolicy,
26223
+ variables: { filter: filter.asPodObject(), interval: toNumber(opts === null || opts === void 0 ? void 0 : opts.interval, 10) },
26194
26224
  error: {
26195
26225
  code: SocialErrorCodes.SUBSCRIBE_USER_EVENTS_ERROR,
26196
26226
  message: 'SOCIAL.ERROR.SUBSCRIBE_USER_EVENTS_ERROR'
26197
26227
  }
26198
- }).pipe(map(({ data }) => {
26228
+ }).pipe(mergeMap(({ data }) => __awaiter(this, void 0, void 0, function* () {
26199
26229
  if (data && this._debug)
26200
26230
  console.debug(`${this._logPrefix}Received new user events:`, data);
26201
- const updatedData = data === null || data === void 0 ? void 0 : data.map(value => this.processUserEvent(value, this));
26202
- // Update cache
26203
- this.insertIntoMutableCachedQueries(this.graphql.cache, {
26204
- query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26205
- data: updatedData
26206
- });
26207
- return updatedData;
26208
- }));
26231
+ // Update cache (will update watchAll queries)
26232
+ if (isNotEmptyArray(data)) {
26233
+ this.insertIntoMutableCachedQueries(this.graphql.cache, {
26234
+ query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26235
+ data: data
26236
+ });
26237
+ }
26238
+ // Convert to entities
26239
+ if (!opts || opts.toEntity !== false) {
26240
+ return yield Promise.all((data || []).map(value => this.processUserEvent(value, this)));
26241
+ }
26242
+ else {
26243
+ return data;
26244
+ }
26245
+ })));
26209
26246
  }
26210
26247
  delete(entity) {
26211
26248
  return __awaiter(this, void 0, void 0, function* () {
@@ -26291,7 +26328,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26291
26328
  .map(entity => this.save(entity, opts)));
26292
26329
  });
26293
26330
  }
26294
- markAsRead(entities) {
26331
+ markAllAsRead(entities) {
26295
26332
  return __awaiter(this, void 0, void 0, function* () {
26296
26333
  const userEventWithoutReadListeners = [];
26297
26334
  for (const entity of (entities || [])) {
@@ -26348,22 +26385,27 @@ class AbstractUserEventService extends BaseGraphqlService {
26348
26385
  this._listenSubscription = undefined;
26349
26386
  }
26350
26387
  processUserEvent(source, that) {
26351
- that = that || this;
26352
- // Convert json source to IUserEvent
26353
- let target = that.fromObject(source);
26354
- // Get listeners
26355
- const listeners = (that.listeners || []).filter(listener => listener.onReceived).filter(listener => listener.accept(target));
26356
- for (const listener of listeners) {
26357
- if (target) {
26358
- target = listener.onReceived(target);
26359
- }
26360
- else {
26361
- if (that._debug)
26362
- console.debug(`${that._logPrefix}Event has been rejected by a listener`, source);
26363
- break;
26388
+ return __awaiter(this, void 0, void 0, function* () {
26389
+ that = that || this;
26390
+ // Convert json source to IUserEvent
26391
+ let target = that.fromObject(source);
26392
+ // Get listeners
26393
+ const listeners = (that.listeners || [])
26394
+ .filter(listener => !!listener.onReceived)
26395
+ .filter(listener => listener.accept(target));
26396
+ for (const listener of listeners) {
26397
+ if (target) {
26398
+ const res = listener.onReceived(target);
26399
+ target = (res instanceof Promise) ? yield res : res;
26400
+ }
26401
+ else {
26402
+ if (that._debug)
26403
+ console.debug(`${that._logPrefix}Event has been rejected by a listener`, source);
26404
+ break;
26405
+ }
26364
26406
  }
26365
- }
26366
- return target;
26407
+ return target;
26408
+ });
26367
26409
  }
26368
26410
  defaultMarkAsRead(userEvents) {
26369
26411
  var _a;
@@ -26449,44 +26491,55 @@ class UserEventNotificationList {
26449
26491
  this.popoverController = popoverController;
26450
26492
  this.settings = settings;
26451
26493
  this.userEventService = userEventService;
26452
- this.subscriptions = new Subscription();
26453
- this._fetchingMore = false;
26494
+ this._subscriptions = new Subscription();
26495
+ this._$pageSize = new BehaviorSubject(20);
26496
+ this.fetchingMore = false;
26497
+ this.$items = new BehaviorSubject(undefined);
26498
+ this.$itemCount = new BehaviorSubject(undefined);
26454
26499
  this.debug = false;
26455
- this.pageSize = 10;
26456
26500
  this.sortBy = 'creationDate';
26457
26501
  this.sortDirection = 'desc';
26458
26502
  this.enableInfiniteScroll = true;
26459
- this.$items = new BehaviorSubject(undefined);
26460
- this.$itemCount = new BehaviorSubject(undefined);
26461
26503
  this.mobile = ((_a = this.settings) === null || _a === void 0 ? void 0 : _a.mobile) || false;
26462
26504
  }
26505
+ set pageSize(value) {
26506
+ if (value > 0 && value !== this._$pageSize.value)
26507
+ this._$pageSize.next(value);
26508
+ }
26509
+ get pageSize() {
26510
+ return this._$pageSize.value;
26511
+ }
26463
26512
  get canFetchMore() {
26464
26513
  return this.enableInfiniteScroll && !!this._fetchMoreFn;
26465
26514
  }
26466
26515
  ngOnInit() {
26467
26516
  // Watch all user events
26468
26517
  if (this.userEventService) {
26469
- this.subscriptions.add(this.userEventService
26470
- .watchAll(0, this.pageSize, this.sortBy, this.sortDirection, this.filter)
26518
+ this._subscriptions.add(this._$pageSize.pipe(distinctUntilChanged(), switchMap(pageSize => this.userEventService.watchAll(0, pageSize, this.sortBy, this.sortDirection, this.filter)))
26471
26519
  .subscribe(result => {
26472
26520
  var _a;
26473
26521
  if (this.debug)
26474
- console.debug(`[user-event-notification-list] receiving ${result.total} user events`, result.data);
26522
+ console.debug(`[user-event-notification-list] Receiving ${result.total} user events`, result.data);
26475
26523
  this.$items.next(result.data);
26476
26524
  this.$itemCount.next(result.total || ((_a = result.data) === null || _a === void 0 ? void 0 : _a.length) || 0);
26477
26525
  this._fetchMoreFn = result.fetchMore;
26526
+ this.fetchingMore = false; // Allow to refetch more
26478
26527
  this.markForCheck();
26479
26528
  }));
26480
26529
  // Listen changes
26481
- this.subscriptions.add(this.userEventService.listenChanges(undefined)
26530
+ this._subscriptions.add(this.userEventService.listenAllChanges(this.filter)
26482
26531
  .subscribe(data => {
26483
26532
  if (this.debug)
26484
- console.debug(`[user-event-notification-list] receiving ${data.length} new user events`, data);
26533
+ console.debug(`[user-event-notification-list] Receiving ${data.length} new user events (by WS)`, data);
26485
26534
  }));
26535
+ if (this.enableInfiniteScroll)
26536
+ this.initInfiniteScroll();
26486
26537
  }
26487
26538
  }
26488
26539
  ngOnDestroy() {
26489
- this.subscriptions.unsubscribe();
26540
+ this._subscriptions.unsubscribe();
26541
+ this.$items.complete();
26542
+ this.$itemCount.complete();
26490
26543
  }
26491
26544
  click(event, userEvent) {
26492
26545
  if (!userEvent)
@@ -26536,47 +26589,59 @@ class UserEventNotificationList {
26536
26589
  }
26537
26590
  dismiss() {
26538
26591
  this.popoverController.dismiss();
26592
+ // Reset counter (need if event has been received while popover if open)
26593
+ this.userEventService.resetCount();
26539
26594
  }
26540
26595
  fetchMore(event) {
26541
26596
  var _a;
26542
26597
  return __awaiter(this, void 0, void 0, function* () {
26543
- if (!this._fetchMoreFn || this._fetchingMore)
26598
+ if (!this._fetchMoreFn || this.fetchingMore)
26544
26599
  return;
26545
26600
  console.debug('[user-event-notification-list] Fetching more notifications...', event);
26546
- this._fetchingMore = true;
26601
+ this.fetchingMore = true;
26602
+ const fetchMoreFn = this._fetchMoreFn;
26547
26603
  try {
26548
- const result = yield this._fetchMoreFn();
26604
+ const result = yield fetchMoreFn();
26549
26605
  let data = [
26550
26606
  ...(this.$items.value || []),
26551
26607
  ...result.data
26552
26608
  ];
26553
26609
  // Remove duplication (e.g. when new user event was added by subscription)
26554
26610
  data = removeDuplicatesFromArray(data, 'id');
26611
+ // fetch more changes (e.g. if watchAll observable as been refreshed)
26612
+ if (fetchMoreFn !== this._fetchMoreFn)
26613
+ return; // Skip
26555
26614
  this.$items.next(data);
26556
26615
  this.$itemCount.next(result.total || ((_a = result.data) === null || _a === void 0 ? void 0 : _a.length) || 0);
26557
26616
  this._fetchMoreFn = result.fetchMore;
26617
+ // Update the page size, to keep same scroll height, after the next refresh
26618
+ this.pageSize = Math.max(this.pageSize, data.length);
26558
26619
  }
26559
26620
  catch (err) {
26560
26621
  console.error(err);
26561
- this._fetchMoreFn = undefined;
26622
+ this._fetchMoreFn = undefined; // Forget the function
26562
26623
  }
26563
26624
  finally {
26564
26625
  this.markForCheck();
26565
- this._fetchingMore = false;
26626
+ this.fetchingMore = false;
26566
26627
  }
26567
26628
  });
26568
26629
  }
26569
- _initInfiniteScroll(threshold) {
26630
+ trackByFn(index, item) {
26631
+ return item.id;
26632
+ }
26633
+ initInfiniteScroll(threshold) {
26570
26634
  return __awaiter(this, void 0, void 0, function* () {
26635
+ console.debug('[user-event-notification-list] Init infinite loop');
26571
26636
  if (this._fetchMoreSubscription)
26572
26637
  this._fetchMoreSubscription.unsubscribe();
26573
26638
  threshold = threshold || (this.mobile ? '15%' : '2%');
26574
- yield waitFor(() => !!this.ionContent);
26639
+ yield waitFor(() => !!this.ionContent, { dueTime: 250, timeout: 1000 });
26575
26640
  const panel = yield this.ionContent.getScrollElement();
26576
26641
  // Trigger fetch more, end end scroll reached
26577
- this._fetchMoreSubscription = fromScrollEndEvent(panel, threshold, 250 /*force to check when no scrollbar - e.g. in large screen*/)
26642
+ this._fetchMoreSubscription = this.$items.pipe(debounceTime(250), filter(() => this.canFetchMore), switchMap(() => fromScrollEndEvent(panel, threshold, 250 /*force to check when no scrollbar - e.g. in large screen*/)))
26578
26643
  .subscribe(() => this.fetchMore());
26579
- this.subscriptions.add(this._fetchMoreSubscription);
26644
+ this._subscriptions.add(this._fetchMoreSubscription);
26580
26645
  });
26581
26646
  }
26582
26647
  markForCheck() {
@@ -26586,9 +26651,9 @@ class UserEventNotificationList {
26586
26651
  UserEventNotificationList.decorators = [
26587
26652
  { type: Component, args: [{
26588
26653
  selector: 'app-user-event-notification-list',
26589
- template: "<ion-content>\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-col class=\"top-action\" *ngIf=\"$items|async|isNotEmptyArray\">\n <ion-text color=\"primary\">\n <a (click)=\"markAllAsRead($event)\">{{'SOCIAL.USER_EVENT.NOTIFICATION.READ_ALL' | translate}}</a>\n </ion-text>\n </ion-col>\n </ion-row>\n\n <ion-item\n *ngFor=\"let item of $items | async; last as last\"\n [lines]=\"last ? 'none' : undefined\"\n [class.unread]=\"!item.readDate\"\n [class.tappable]=\"item.actions|arrayFilter:isDefaultAction|isNotEmptyArray\"\n (click)=\"click($event, item)\">\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"item.avatar; else avatarIcon\" src=\"{{ item.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"item.avatarIcon\"\n [ref]=\"item.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 message\">\n <ion-row>\n <ion-col size=\"12\">\n <p [class.unread]=\"!item.readDate\" [innerHTML]=\"item.message\"></p>\n </ion-col>\n </ion-row>\n\n <!-- date -->\n <ion-row>\n <ion-col size=\"12\">\n <app-icon\n *ngIf=\"item.icon\"\n [ref]=\"item.icon\"\n height=\"16\"\n width=\"16\"\n style=\"vertical-align: sub; margin-right: 3px\"\n ></app-icon>\n <small>\n <span>{{item.creationDate|dateFromNow}}</span>\n <span style=\"color: gray\">{{ ' | ' + (item.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n\n <!-- actions -->\n <ion-row *ngIf=\"item.actions|isNotEmptyArray\">\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ng-container *ngFor=\"let action of item.actions\">\n <a *ngIf=\"!action.default\" class=\"action\" (click)=\"executeAction($event, action, item)\" [title]=\"(action.title || action.name) |translate\">\n <app-icon *ngIf=\"action.iconRef\" slot=\"start\" height=\"20\" width=\"20\" [ref]=\"action.iconRef\"></app-icon>\n <span>{{ action.name | translate }}</span>\n </a>\n </ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <mat-icon slot=\"end\" *ngIf=\"item.actions|arrayFilter: isDefaultAction|isNotEmptyArray\">chevron_right</mat-icon>\n </ion-item>\n\n <!-- loading -->\n <ion-item *ngIf=\"!($items|async); else noResult\" lines=\"none\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </ion-item>\n\n <!-- no result -->\n <ng-template #noResult>\n <ion-item *ngIf=\"$items|async|isEmptyArray\" lines=\"none\">\n <ion-text color=\"dark\" class=\"text-italic\">{{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}</ion-text>\n </ion-item>\n </ng-template>\n\n <!-- Loading more spinner -->\n <ion-item *ngIf=\"canFetchMore\" (ngInit)=\"_initInfiniteScroll()\" lines=\"none\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </ion-item>\n\n <!-- footer -->\n <ion-row *ngIf=\"$itemCount|async; let count\"\n class=\"ion-list-footer column\">\n <ion-col>\n <ion-text class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n </ion-list>\n</ion-content>\n",
26654
+ template: "<ion-content>\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-col class=\"top-action\" *ngIf=\"$items|async|isNotEmptyArray\">\n <ion-text color=\"primary\">\n <a (click)=\"markAllAsRead($event)\">{{'SOCIAL.USER_EVENT.NOTIFICATION.READ_ALL' | translate}}</a>\n </ion-text>\n </ion-col>\n </ion-row>\n\n <ion-item\n *ngFor=\"let item of $items | async; trackBy: trackByFn; last as last\"\n [lines]=\"last ? 'none' : undefined\"\n [class.unread]=\"!item.readDate\"\n [class.tappable]=\"item.actions|arrayFilter:isDefaultAction|isNotEmptyArray\"\n (click)=\"click($event, item)\">\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"item.avatar; else avatarIcon\" src=\"{{ item.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"item.avatarIcon; else generateIcon\"\n [ref]=\"item.avatarIcon\"\n height=\"40\"\n width=\"40\"\n ></app-icon>\n </ng-template>\n\n <ng-template #generateIcon>\n <div class=\"avatar\" *ngIf=\"item.avatarJdenticon\">\n <svg width=\"40\" width=\"40\" [data-jdenticon-value]=\"item.avatarJdenticon\"></svg>\n </div>\n </ng-template>\n\n </ion-avatar>\n\n <ion-grid class=\"ion-no-margin ion-no-padding message\">\n <ion-row>\n <ion-col size=\"12\">\n <p [class.unread]=\"!item.readDate\" [innerHTML]=\"item.message\"></p>\n </ion-col>\n </ion-row>\n\n <!-- date -->\n <ion-row>\n <ion-col size=\"12\">\n <app-icon\n *ngIf=\"item.icon\"\n [ref]=\"item.icon\"\n height=\"16\"\n width=\"16\"\n style=\"vertical-align: sub; margin-right: 3px\"\n ></app-icon>\n <small>\n <span>{{item.creationDate|dateFromNow}}</span>\n <span style=\"color: gray\">{{ ' | ' + (item.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n\n <!-- actions -->\n <ion-row *ngIf=\"item.actions|isNotEmptyArray\">\n <ion-col></ion-col>\n <ion-col size=\"auto\">\n <ng-container *ngFor=\"let action of item.actions\">\n <a *ngIf=\"!action.default\" class=\"action\" (click)=\"executeAction($event, action, item)\" [title]=\"(action.title || action.name) |translate\">\n <app-icon *ngIf=\"action.iconRef\" slot=\"start\" height=\"20\" width=\"20\" [ref]=\"action.iconRef\"></app-icon>\n <span>{{ action.name | translate }}</span>\n </a>\n </ng-container>\n </ion-col>\n </ion-row>\n\n </ion-grid>\n\n <mat-icon slot=\"end\" *ngIf=\"item.actions|arrayFilter: isDefaultAction|isNotEmptyArray\">chevron_right</mat-icon>\n </ion-item>\n\n <!-- loading -->\n <ng-container *ngIf=\"!($items|async); else notLoading\">\n <ng-container *ngTemplateOutlet=\"loadingItem\"></ng-container>\n </ng-container>\n\n <ng-template #notLoading>\n <!-- no result -->\n <ion-item *ngIf=\"$items|async|isEmptyArray\" lines=\"none\">\n <ion-text color=\"dark\" class=\"text-italic\">{{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}</ion-text>\n </ion-item>\n\n <!-- Fetching more -->\n <ng-container *ngIf=\"fetchingMore; else infiniteLoop\" lines=\"none\" disabled>\n <ng-container *ngTemplateOutlet=\"loadingItem\"></ng-container>\n </ng-container>\n\n <!-- Infinite loop -->\n <ng-template #infiniteLoop>\n <ng-container *ngIf=\"canFetchMore\" lines=\"none\" disabled\n [ngTemplateOutlet]=\"loadingItem\">\n </ng-container>\n </ng-template>\n </ng-template>\n\n <!-- footer -->\n <ion-row class=\"ion-list-footer column\">\n <ion-col>\n <ion-text *ngIf=\"$itemCount|async; let count\"\n class=\"ion-float-end ion-padding-end\"><i>{{'COMMON.RESULT_COUNT'|translate: {count: count} }}</i></ion-text>\n </ion-col>\n </ion-row>\n\n </ion-list>\n</ion-content>\n\n<!-- loading -->\n<ng-template #loadingItem>\n <ion-item lines=\"none\" disabled>\n <ion-skeleton-text [animated]=\"true\" style=\"width: 100%\"></ion-skeleton-text>\n </ion-item>\n</ng-template>\n",
26590
26655
  changeDetection: ChangeDetectionStrategy.OnPush,
26591
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;max-height:calc(90vh - 20px)}ion-list ion-item.tappable{cursor:pointer}ion-list ion-item.tappable:hover{--ion-item-background:var(--ion-item-background-color-hover)}.message{font-size:.9em}.message p{margin-top:5px;margin-bottom:5px}.message p.unread{font-weight:700}.top-action{text-align:end;margin-right:8px}.top-action a{cursor:pointer;color:var(--ion-color-contrast)}.top-action a:hover{text-decoration:underline}a.action{font-size:.9em;margin-right:10px;cursor:pointer}a.action:hover span{text-decoration:underline}a.action app-icon{vertical-align:middle}"]
26656
+ styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none;max-height:calc(90vh - 20px)}ion-list ion-item.tappable{cursor:pointer}ion-list ion-item.tappable:hover{--ion-item-background:var(--ion-item-background-color-hover)}.message{font-size:.9em}.message p{margin-top:5px;margin-bottom:5px}.message p.unread{font-weight:700}.top-action{text-align:end;margin-right:8px}.top-action a{cursor:pointer;color:var(--ion-color-contrast)}.top-action a:hover{text-decoration:underline}a.action{font-size:.9em;margin-right:10px;cursor:pointer}a.action:hover span{text-decoration:underline}a.action app-icon{vertical-align:middle}ion-avatar .avatar svg,ion-avatar img{border:1px solid rgba(var(--ion-color-secondary-rgb,.5));border-radius:50%}"]
26592
26657
  },] }
26593
26658
  ];
26594
26659
  UserEventNotificationList.ctorParameters = () => [
@@ -26601,11 +26666,11 @@ UserEventNotificationList.propDecorators = {
26601
26666
  debug: [{ type: Input }],
26602
26667
  mobile: [{ type: Input }],
26603
26668
  titleI18n: [{ type: Input }],
26604
- pageSize: [{ type: Input }],
26605
26669
  sortBy: [{ type: Input }],
26606
26670
  sortDirection: [{ type: Input }],
26607
26671
  filter: [{ type: Input }],
26608
26672
  enableInfiniteScroll: [{ type: Input }],
26673
+ pageSize: [{ type: Input }],
26609
26674
  readEvent: [{ type: Output }],
26610
26675
  readEvents: [{ type: Output }],
26611
26676
  ionContent: [{ type: ViewChild, args: [IonContent,] }],
@@ -26642,12 +26707,12 @@ class AppUserEventNotificationIcon {
26642
26707
  // Wait service
26643
26708
  yield this.userEventService.ready();
26644
26709
  // Subscribe to read event
26645
- this._readEvent.subscribe(value => {
26710
+ this._readEvent.subscribe(item => {
26646
26711
  // default: mark event as read
26647
- this.userEventService.markAsRead([value]);
26712
+ this.userEventService.markAllAsRead([item]);
26648
26713
  });
26649
- this._readEvents.subscribe(value => {
26650
- this.userEventService.markAsRead(value);
26714
+ this._readEvents.subscribe(items => {
26715
+ this.userEventService.markAllAsRead(items);
26651
26716
  });
26652
26717
  });
26653
26718
  }
@@ -26661,7 +26726,8 @@ class AppUserEventNotificationIcon {
26661
26726
  debug: this.debug,
26662
26727
  titleI18n: this.titleI18n,
26663
26728
  readEvent: this._readEvent,
26664
- readEvents: this._readEvents
26729
+ readEvents: this._readEvents,
26730
+ filter: this.filter
26665
26731
  },
26666
26732
  backdropDismiss: true,
26667
26733
  keyboardClose: true,
@@ -26704,7 +26770,8 @@ UserEventModule.decorators = [
26704
26770
  imports: [
26705
26771
  CommonModule,
26706
26772
  SharedModule,
26707
- AppIconModule
26773
+ AppIconModule,
26774
+ NgxJdenticonModule
26708
26775
  ],
26709
26776
  declarations: [
26710
26777
  AppUserEventNotificationIcon,
@@ -27023,7 +27090,7 @@ JobProgressionList.decorators = [
27023
27090
  { type: Component, args: [{
27024
27091
  selector: 'app-job-progression-list',
27025
27092
  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\" class=\"ion-item-job-progression\">\n <ion-grid class=\"ion-no-margin\">\n <ion-row class=\"name\">\n <ion-col>\n {{jobProgression.name}}\n </ion-col>\n </ion-row>\n <ion-row class=\"message\">\n <ion-col>\n {{jobProgression.message}}\n </ion-col>\n </ion-row>\n <ion-row class=\"progress-bar\">\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",
27026
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ion-item-job-progression{font-size:.9em}.ion-item-job-progression .message{font-style:italic}.ion-item-job-progression .progress-bar{margin-top:5px;margin-bottom:5px}"]
27093
+ styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}.ion-item-job-progression{font-size:.9em}.ion-item-job-progression .message{font-style:italic}.ion-item-job-progression .progress-bar{margin-top:5px;margin-bottom:5px}"]
27027
27094
  },] }
27028
27095
  ];
27029
27096
  JobProgressionList.ctorParameters = () => [];
@@ -27263,130 +27330,6 @@ SocialModule.decorators = [
27263
27330
  },] }
27264
27331
  ];
27265
27332
 
27266
- var UserEvent_1;
27267
- const UserEventTypes = {
27268
- DEBUG_DATA: 'DEBUG_DATA',
27269
- INBOX_MESSAGE: 'INBOX_MESSAGE'
27270
- };
27271
- // @dynamic
27272
- let UserEvent = UserEvent_1 = class UserEvent extends Entity {
27273
- constructor() {
27274
- super(UserEvent_1.TYPENAME);
27275
- }
27276
- asObject(opts) {
27277
- const target = super.asObject(opts);
27278
- target.creationDate = toDateISOString(this.creationDate);
27279
- target.readDate = toDateISOString(this.readDate);
27280
- // Serialize content
27281
- if (typeof target.content === 'object') {
27282
- target.content = JSON.stringify(target.content);
27283
- }
27284
- delete target.avatar;
27285
- delete target.avatarIcon;
27286
- delete target.icon;
27287
- delete target.actions;
27288
- return target;
27289
- }
27290
- fromObject(source) {
27291
- Object.assign(this, source); // Copy all properties
27292
- super.fromObject(source);
27293
- this.creationDate = fromDateISOString(source.creationDate);
27294
- this.readDate = fromDateISOString(source.readDate);
27295
- try {
27296
- // Deserialize content
27297
- if (typeof source.content === 'string' && source.content.startsWith('{')) {
27298
- this.content = JSON.parse(source.content);
27299
- }
27300
- // Deserialize content.context
27301
- if (this.content && typeof this.content.context === 'string' && this.content.context.startsWith('{')) {
27302
- this.content.context = JSON.parse(this.content.context);
27303
- }
27304
- }
27305
- catch (err) {
27306
- console.error('Error during UserEvent deserialization', err);
27307
- }
27308
- }
27309
- };
27310
- UserEvent = UserEvent_1 = __decorate([
27311
- EntityClass({ typename: 'UserEventVO' })
27312
- ], UserEvent);
27313
- // @dynamic
27314
- let UserEventFilter = class UserEventFilter extends EntityFilter {
27315
- constructor() {
27316
- super(...arguments);
27317
- this.types = [];
27318
- this.levels = [];
27319
- this.issuers = [];
27320
- this.recipients = [];
27321
- this.startDate = null;
27322
- this.excludeRead = false;
27323
- }
27324
- fromObject(source, opts) {
27325
- super.fromObject(source, opts);
27326
- this.types = source.types || [];
27327
- this.levels = source.levels || [];
27328
- this.issuers = source.issuers || [];
27329
- this.recipients = source.recipients || [];
27330
- this.startDate = fromDateISOString(source.startDate);
27331
- this.excludeRead = source.excludeRead || false;
27332
- }
27333
- buildFilter() {
27334
- const filterFns = super.buildFilter();
27335
- if (isNotEmptyArray(this.types)) {
27336
- filterFns.push(t => this.types.includes(t.type));
27337
- }
27338
- if (isNotEmptyArray(this.levels)) {
27339
- filterFns.push(t => this.levels.includes(t.level));
27340
- }
27341
- if (isNotEmptyArray(this.issuers)) {
27342
- filterFns.push(t => this.issuers.includes(t.issuer));
27343
- }
27344
- if (isNotEmptyArray(this.recipients)) {
27345
- filterFns.push(t => this.recipients.includes(t.recipient));
27346
- }
27347
- if (isNotNil(this.startDate)) {
27348
- filterFns.push(t => this.startDate.isSameOrBefore(t.creationDate));
27349
- }
27350
- if (this.excludeRead === true) {
27351
- filterFns.push(t => isNil(t.readSignature)); // todo or t.signature ?
27352
- }
27353
- return filterFns;
27354
- }
27355
- asObject(opts) {
27356
- const target = super.asObject(opts);
27357
- return target;
27358
- }
27359
- };
27360
- UserEventFilter = __decorate([
27361
- EntityClass({ typename: 'UserEventFilterVO' })
27362
- ], UserEventFilter);
27363
-
27364
- const UserEventFragments = {
27365
- userEvent: gql `fragment UserEventFragment on UserEventVO {
27366
- id
27367
- issuer
27368
- updateDate
27369
- creationDate
27370
- eventType
27371
- recipient
27372
- content
27373
- hash
27374
- signature
27375
- readSignature
27376
- __typename
27377
- }`,
27378
- lightUserEvent: gql `fragment LightUserEventFragment on UserEventVO {
27379
- id
27380
- issuer
27381
- recipient
27382
- updateDate
27383
- creationDate
27384
- eventType
27385
- readSignature
27386
- __typename
27387
- }`
27388
- };
27389
-
27390
27333
  const Mutations = {
27391
27334
  send: gql `mutation SendMessage($data: MessageVOInput){
27392
27335
  done: sendMessage(message: $data)
@@ -27729,7 +27672,6 @@ class UsersPage extends AppTable {
27729
27672
  this.statusById = StatusById;
27730
27673
  this.filterCriteriaCount = 0;
27731
27674
  this.useSticky = false;
27732
- this.referentialToString = referentialToString;
27733
27675
  this.canEdit = accountService.isAdmin();
27734
27676
  this.canSendMessage = this.canEdit;
27735
27677
  this.inlineEdition = this.canEdit;
@@ -29402,6 +29344,100 @@ JobTestingModule.decorators = [
29402
29344
  },] }
29403
29345
  ];
29404
29346
 
29347
+ var UserEventTest_1;
29348
+ // @dynamic
29349
+ let UserEventTest = UserEventTest_1 = class UserEventTest extends Entity {
29350
+ constructor() {
29351
+ super(UserEventTest_1.TYPENAME);
29352
+ }
29353
+ asObject(opts) {
29354
+ const target = super.asObject(opts);
29355
+ target.creationDate = toDateISOString(this.creationDate);
29356
+ target.readDate = toDateISOString(this.readDate);
29357
+ // Serialize content
29358
+ if (typeof target.content === 'object') {
29359
+ target.content = JSON.stringify(target.content);
29360
+ }
29361
+ delete target.avatar;
29362
+ delete target.avatarIcon;
29363
+ delete target.icon;
29364
+ delete target.actions;
29365
+ return target;
29366
+ }
29367
+ fromObject(source) {
29368
+ Object.assign(this, source); // Copy all properties
29369
+ super.fromObject(source);
29370
+ this.creationDate = fromDateISOString(source.creationDate);
29371
+ this.readDate = fromDateISOString(source.readDate);
29372
+ try {
29373
+ // Deserialize content
29374
+ if (typeof source.content === 'string' && source.content.startsWith('{')) {
29375
+ this.content = JSON.parse(source.content);
29376
+ }
29377
+ // Deserialize content.context
29378
+ if (this.content && typeof this.content.context === 'string' && this.content.context.startsWith('{')) {
29379
+ this.content.context = JSON.parse(this.content.context);
29380
+ }
29381
+ }
29382
+ catch (err) {
29383
+ console.error('Error during UserEvent deserialization', err);
29384
+ }
29385
+ }
29386
+ };
29387
+ UserEventTest = UserEventTest_1 = __decorate([
29388
+ EntityClass({ typename: 'UserEventTestVO' })
29389
+ ], UserEventTest);
29390
+ // @dynamic
29391
+ let UserEventTestFilter = class UserEventTestFilter extends EntityFilter {
29392
+ constructor() {
29393
+ super(...arguments);
29394
+ this.types = [];
29395
+ this.levels = [];
29396
+ this.issuers = [];
29397
+ this.recipients = [];
29398
+ this.startDate = null;
29399
+ this.excludeRead = false;
29400
+ }
29401
+ fromObject(source, opts) {
29402
+ super.fromObject(source, opts);
29403
+ this.types = source.types || [];
29404
+ this.levels = source.levels || [];
29405
+ this.issuers = source.issuers || [];
29406
+ this.recipients = source.recipients || [];
29407
+ this.startDate = fromDateISOString(source.startDate);
29408
+ this.excludeRead = source.excludeRead || false;
29409
+ }
29410
+ buildFilter() {
29411
+ const filterFns = super.buildFilter();
29412
+ if (isNotEmptyArray(this.types)) {
29413
+ filterFns.push(t => this.types.includes(t.type));
29414
+ }
29415
+ if (isNotEmptyArray(this.levels)) {
29416
+ filterFns.push(t => this.levels.includes(t.level));
29417
+ }
29418
+ if (isNotEmptyArray(this.issuers)) {
29419
+ filterFns.push(t => this.issuers.includes(t.issuer));
29420
+ }
29421
+ if (isNotEmptyArray(this.recipients)) {
29422
+ filterFns.push(t => this.recipients.includes(t.recipient));
29423
+ }
29424
+ if (isNotNil(this.startDate)) {
29425
+ filterFns.push(t => this.startDate.isSameOrBefore(t.creationDate));
29426
+ }
29427
+ if (this.excludeRead === true) {
29428
+ filterFns.push(t => isNil(t.readSignature)); // todo or t.signature ?
29429
+ }
29430
+ return filterFns;
29431
+ }
29432
+ asObject(opts) {
29433
+ const target = super.asObject(opts);
29434
+ return target;
29435
+ }
29436
+ };
29437
+ UserEventTestFilter = __decorate([
29438
+ EntityClass({ typename: 'UserEventTestFilterVO' })
29439
+ ], UserEventTestFilter);
29440
+
29405
29441
  class UserEventTestService extends AbstractUserEventService {
29406
29442
  constructor(graphql, accountService, network, translate, environment) {
29407
29443
  super(graphql, accountService, network, translate, {
@@ -29416,25 +29452,31 @@ class UserEventTestService extends AbstractUserEventService {
29416
29452
  this.network = network;
29417
29453
  this.translate = translate;
29418
29454
  this.environment = environment;
29419
- this.userEvents = [];
29455
+ this.$userEvents = new BehaviorSubject([]);
29456
+ this.$newUserEvents = new Subject();
29420
29457
  }
29421
29458
  fromObject(source) {
29422
- return UserEvent.fromObject(source);
29459
+ return UserEventTest.fromObject(source);
29423
29460
  }
29424
29461
  add(entity) {
29425
- entity = this.processUserEvent(entity);
29426
- entity.id = this.userEvents.length + 1;
29427
- this.userEvents = [
29428
- entity,
29429
- ...this.userEvents
29430
- ];
29431
- this._countSubject.next((this._countSubject.value || 0) + 1);
29462
+ var _a;
29463
+ return __awaiter(this, void 0, void 0, function* () {
29464
+ entity = yield this.processUserEvent(entity);
29465
+ entity.id = (((_a = this.$userEvents.value) === null || _a === void 0 ? void 0 : _a.length) || 0) + 1;
29466
+ this.$userEvents.next([
29467
+ entity,
29468
+ ...this.$userEvents.value
29469
+ ]);
29470
+ this._countSubject.next((this._countSubject.value || 0) + 1);
29471
+ this.$newUserEvents.next([entity]);
29472
+ });
29432
29473
  }
29433
29474
  asFilter(filter) {
29434
29475
  return filter;
29435
29476
  }
29436
29477
  count(filter, options) {
29437
- return Promise.resolve(this.userEvents.length);
29478
+ var _a;
29479
+ return Promise.resolve(((_a = this.$userEvents.value) === null || _a === void 0 ? void 0 : _a.length) || 0);
29438
29480
  }
29439
29481
  delete(entity) {
29440
29482
  return Promise.resolve(undefined);
@@ -29442,12 +29484,12 @@ class UserEventTestService extends AbstractUserEventService {
29442
29484
  deleteAll(data, opts) {
29443
29485
  return Promise.resolve(undefined);
29444
29486
  }
29445
- listenChanges(filter, options) {
29446
- return of();
29487
+ listenAllChanges(filter, options) {
29488
+ return this.$newUserEvents.asObservable();
29447
29489
  }
29448
29490
  save(entity, options) {
29449
29491
  var _a;
29450
- const toSave = (_a = this.userEvents) === null || _a === void 0 ? void 0 : _a.find(value => value.id == (entity === null || entity === void 0 ? void 0 : entity.id));
29492
+ const toSave = (_a = this.$userEvents.value) === null || _a === void 0 ? void 0 : _a.find(value => value.id == (entity === null || entity === void 0 ? void 0 : entity.id));
29451
29493
  Object.assign(toSave, entity);
29452
29494
  return entity;
29453
29495
  }
@@ -29456,27 +29498,29 @@ class UserEventTestService extends AbstractUserEventService {
29456
29498
  for (const entity of (data || [])) {
29457
29499
  yield this.save(entity);
29458
29500
  }
29459
- return Promise.resolve(this.userEvents);
29501
+ return this.$userEvents.toPromise();
29460
29502
  });
29461
29503
  }
29462
29504
  watchAll(offset, size, sortBy, sortDirection, filter, opts) {
29463
- var _a;
29464
- let data = (this.userEvents || []).slice(offset || 0, offset + size);
29465
- const total = ((_a = this.userEvents) === null || _a === void 0 ? void 0 : _a.length) || 0;
29466
- const res = { data, total };
29467
- // Must re-order because of listenChanges result will add new event at the end
29468
- data = EntityUtils.sort(data, sortBy, sortDirection);
29469
- // Add fetch more
29470
- const nextOffset = offset + data.length;
29471
- if (nextOffset < res.total) {
29472
- res.fetchMore = (_) => this.loadAll(nextOffset, size, sortBy, sortDirection, filter, Object.assign(Object.assign({}, opts), { fetchPolicy: 'no-cache' }));
29473
- }
29474
- return of(res);
29505
+ return this.$userEvents.pipe(map(userEvents => {
29506
+ var _a;
29507
+ let data = (userEvents || []).slice(offset || 0, offset + size);
29508
+ const total = ((_a = this.$userEvents.value) === null || _a === void 0 ? void 0 : _a.length) || 0;
29509
+ const res = { data, total };
29510
+ // Must re-order because of listenChanges result will add new event at the end
29511
+ data = EntityUtils.sort(data, sortBy, sortDirection);
29512
+ // Add fetch more
29513
+ const nextOffset = offset + data.length;
29514
+ if (nextOffset < res.total) {
29515
+ res.fetchMore = (_) => this.loadAll(nextOffset, size, sortBy, sortDirection, filter, Object.assign(Object.assign({}, opts), { fetchPolicy: 'no-cache' }));
29516
+ }
29517
+ return res;
29518
+ }));
29475
29519
  }
29476
29520
  loadAll(offset, size, sortBy, sortDirection, filter, opts) {
29477
29521
  var _a;
29478
- let data = (this.userEvents || []).slice(offset || 0, offset + size);
29479
- const total = ((_a = this.userEvents) === null || _a === void 0 ? void 0 : _a.length) || 0;
29522
+ let data = (this.$userEvents.value || []).slice(offset || 0, offset + size);
29523
+ const total = ((_a = this.$userEvents.value) === null || _a === void 0 ? void 0 : _a.length) || 0;
29480
29524
  const res = { data, total };
29481
29525
  // Must re-order because of listenChanges result will add new event at the end
29482
29526
  data = EntityUtils.sort(data, sortBy, sortDirection);
@@ -29518,6 +29562,12 @@ class UserEventTestingPage {
29518
29562
  onRead: (userEvent) => { this.showMessage("debug message read "); }
29519
29563
  });
29520
29564
  }
29565
+ get timerStarted() {
29566
+ return !!this._timerSubscription;
29567
+ }
29568
+ ngOnDestroy() {
29569
+ this.stopTimer();
29570
+ }
29521
29571
  customize(userEvent) {
29522
29572
  // Choose avatarIcon
29523
29573
  switch (userEvent.level) {
@@ -29548,7 +29598,7 @@ class UserEventTestingPage {
29548
29598
  }
29549
29599
  }
29550
29600
  addNotification() {
29551
- this.userEventService.add(UserEvent.fromObject({
29601
+ this.userEventService.add(UserEventTest.fromObject({
29552
29602
  issuer: 'system',
29553
29603
  recipient: 'me',
29554
29604
  type: 'message',
@@ -29558,7 +29608,7 @@ class UserEventTestingPage {
29558
29608
  }));
29559
29609
  }
29560
29610
  addError() {
29561
- this.userEventService.add(UserEvent.fromObject({
29611
+ this.userEventService.add(UserEventTest.fromObject({
29562
29612
  issuer: 'system',
29563
29613
  recipient: 'me',
29564
29614
  type: 'upload',
@@ -29568,7 +29618,7 @@ class UserEventTestingPage {
29568
29618
  }));
29569
29619
  }
29570
29620
  addWarning() {
29571
- this.userEventService.add(UserEvent.fromObject({
29621
+ this.userEventService.add(UserEventTest.fromObject({
29572
29622
  issuer: 'system',
29573
29623
  recipient: 'me',
29574
29624
  type: 'download',
@@ -29578,7 +29628,7 @@ class UserEventTestingPage {
29578
29628
  }));
29579
29629
  }
29580
29630
  addDebug() {
29581
- this.userEventService.add(UserEvent.fromObject({
29631
+ this.userEventService.add(UserEventTest.fromObject({
29582
29632
  issuer: 'system',
29583
29633
  recipient: 'me',
29584
29634
  type: 'debug',
@@ -29588,7 +29638,7 @@ class UserEventTestingPage {
29588
29638
  }));
29589
29639
  }
29590
29640
  addNotificationWithLink() {
29591
- this.userEventService.add(UserEvent.fromObject({
29641
+ this.userEventService.add(UserEventTest.fromObject({
29592
29642
  issuer: 'system',
29593
29643
  recipient: 'me',
29594
29644
  type: 'message',
@@ -29605,7 +29655,7 @@ class UserEventTestingPage {
29605
29655
  }));
29606
29656
  }
29607
29657
  addNotificationWithAction() {
29608
- this.userEventService.add(UserEvent.fromObject({
29658
+ this.userEventService.add(UserEventTest.fromObject({
29609
29659
  issuer: 'system',
29610
29660
  recipient: 'me',
29611
29661
  type: 'message',
@@ -29632,8 +29682,52 @@ class UserEventTestingPage {
29632
29682
  ]
29633
29683
  }));
29634
29684
  }
29685
+ addMany(count) {
29686
+ count = count || 20;
29687
+ for (let i = 0; i < count; i++) {
29688
+ this.addRandom(i);
29689
+ }
29690
+ }
29691
+ startTimer(period) {
29692
+ var _a;
29693
+ (_a = this._timerSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
29694
+ period = period || 1000;
29695
+ let counter = 0;
29696
+ this._timerSubscription = timer(period, period)
29697
+ .subscribe(() => {
29698
+ this.addRandom(counter);
29699
+ counter++;
29700
+ });
29701
+ }
29702
+ stopTimer() {
29703
+ var _a;
29704
+ (_a = this._timerSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
29705
+ this._timerSubscription = null;
29706
+ }
29707
+ addRandom(value) {
29708
+ switch (value % 6) {
29709
+ case 0:
29710
+ this.addNotification();
29711
+ break;
29712
+ case 1:
29713
+ this.addError();
29714
+ break;
29715
+ case 2:
29716
+ this.addDebug();
29717
+ break;
29718
+ case 3:
29719
+ this.addNotificationWithLink();
29720
+ break;
29721
+ case 4:
29722
+ this.addNotificationWithAction();
29723
+ break;
29724
+ case 5:
29725
+ this.addNotificationWithDefaultAction();
29726
+ break;
29727
+ }
29728
+ }
29635
29729
  addNotificationWithDefaultAction() {
29636
- this.userEventService.add(UserEvent.fromObject({
29730
+ this.userEventService.add(UserEventTest.fromObject({
29637
29731
  issuer: 'system',
29638
29732
  recipient: 'me',
29639
29733
  type: 'message',
@@ -29656,7 +29750,7 @@ class UserEventTestingPage {
29656
29750
  UserEventTestingPage.decorators = [
29657
29751
  { type: Component, args: [{
29658
29752
  selector: 'job-progression-testing',
29659
- template: "<ion-toolbar color=\"primary\">\n <ion-title>User events</ion-title>\n</ion-toolbar>\n\n<ion-content class=\"ion-padding\">\n\n <app-user-event-notification-icon #notification [debug]=\"true\"></app-user-event-notification-icon>\n\n <p>\n <ion-button (click)=\"addNotification()\">Add notification</ion-button>\n <ion-button (click)=\"addError()\">Add error</ion-button>\n <ion-button (click)=\"addWarning()\">Add warning</ion-button>\n <ion-button (click)=\"addDebug()\">Add debug</ion-button>\n </p>\n <p>\n <ion-button (click)=\"addNotificationWithLink()\">Add notification with link</ion-button>\n <ion-button (click)=\"addNotificationWithAction()\">Add notification with action</ion-button>\n <ion-button (click)=\"addNotificationWithDefaultAction()\">Add notification with default action</ion-button>\n </p>\n</ion-content>\n"
29753
+ template: "<ion-toolbar color=\"primary\">\n <ion-title>User events</ion-title>\n</ion-toolbar>\n\n<ion-content class=\"ion-padding\">\n\n <app-user-event-notification-icon #notification [debug]=\"true\"></app-user-event-notification-icon>\n\n <p>\n <ion-button (click)=\"addNotification()\">Add notification</ion-button>\n <ion-button (click)=\"addError()\">Add error</ion-button>\n <ion-button (click)=\"addWarning()\">Add warning</ion-button>\n <ion-button (click)=\"addDebug()\">Add debug</ion-button>\n </p>\n <p>\n <ion-button (click)=\"addNotificationWithLink()\">Add notification with link</ion-button>\n <ion-button (click)=\"addNotificationWithAction()\">Add notification with action</ion-button>\n <ion-button (click)=\"addNotificationWithDefaultAction()\">Add notification with default action</ion-button>\n </p>\n <p>\n <ion-button (click)=\"addMany()\">Add notifications (x20)</ion-button>\n </p>\n <p>\n <ion-button (click)=\"startTimer()\" *ngIf=\"!timerStarted\">Start timer</ion-button>\n <ion-button (click)=\"stopTimer()\" *ngIf=\"timerStarted\">Stop timer</ion-button>\n </p>\n</ion-content>\n"
29660
29754
  },] }
29661
29755
  ];
29662
29756
  UserEventTestingPage.ctorParameters = () => [
@@ -29725,5 +29819,5 @@ SocialTestingModule.decorators = [
29725
29819
  * Generated bundle index. Do not edit.
29726
29820
  */
29727
29821
 
29728
- export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_TESTING_PAGES, AboutModal, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, ActionsColumnComponent, AdminModule, AdminRoutingModule, Alerts, AndroidOsEnvironment, AnimationState, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppForm, AppFormField, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppIconComponent, AppIconModule, AppInMemoryTable, AppInstallUpgradeCard, AppListForm, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppTabEditor, AppTabEditorOptions, AppTable, AppTableDataSourceOptions, AppTableUtils, AppUserEventNotificationIcon, AppValidatorService, AppendToInputDirective, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayLengthPipe, ArrayPluckPipe, AudioProvider, AuthForm, AuthGuardService, AuthModal, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFromNowPipe, DateTimeTestPage, DateUtils, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesService, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, Fragments$1 as Fragments, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, InMemoryEntitiesService, IsLoginAccountPipe, IsNilOrBlankPipe, IsNotNilOrBlankPipe, IsNotOnFieldModePipe, IsOnFieldModePipe, Job, JobModule, JobProgression, JobProgressionComponent, JobProgressionService, JobProgressionServiceToken, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LongitudeFormatPipe, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MapGetPipe, MapKeysPipe, MapValuesPipe, MatAutocompleteConfigHolder, MatAutocompleteField, MatBadgeIconDirective, MatBooleanField, MatChipsField, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatNumpadComponent, MatNumpadContainerComponent, MatNumpadContent, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItems, MenuOptions, MenuService, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NetworkService, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, NumpadDirective, OddPipe, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, ResizableComponent, ResizableDirective, ResizableModule, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SelectPeerModal, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBadgeIconModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatNumpadModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StrIncludesPipe, StrLengthPipe, SwipeTestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TextForm, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, Toasts, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, USER_EVENT_SERVICE, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEvent, UserEventFilter, UserEventFragments, UserEventModule, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserEventTypes, UserSettings, UsersPage, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayGroupBy, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, hexToRgb, hexToRgbArray, isAndroid, isBlankString, isControlHasInput, isCordova, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moment$5 as moment, moveInputCaretToSeparator, noTrailingSlash, notNilOrDefault, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputRange, setCalculatedValue, setTabIndex, sleep, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, tz, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending, ɵ0, CustomReuseStrategy as ɵa, MatNumpadDomService as ɵb, isFocusableElement as ɵc, RegisterForm as ɵd, AccountValidatorService as ɵe, RegisterModal as ɵf, UserSettingsValidatorService as ɵg, LocalSettingsValidatorService as ɵh, AppUpdateOfflineModeCard as ɵi, UserEventNotificationList as ɵj, JobProgressionList as ɵk, DateTestPage as ɵl, NumpadTestPage as ɵm, MatBadgeIconTestPage as ɵn, ToastTestingModule as ɵo, ToastTestingPage as ɵp };
29822
+ export { APP_ABOUT_DEVELOPERS, APP_ABOUT_PARTNERS, APP_CONFIG_OPTIONS, APP_FORM_ERROR_I18N_KEYS, APP_GRAPHQL_TYPE_POLICIES, APP_HOME_BUTTONS, APP_LOCALES, APP_LOCAL_SETTINGS, APP_LOCAL_SETTINGS_OPTIONS, APP_LOCAL_STORAGE_TYPE_POLICIES, APP_MENU_ITEMS, APP_MENU_OPTIONS, APP_TESTING_PAGES, AboutModal, AbstractUserEventService, Account, AccountPage, AccountService, AccountToStringPipe, ActionsColumnComponent, AdminModule, AdminRoutingModule, Alerts, AndroidOsEnvironment, AnimationState, AppEditor, AppEditorOptions, AppEntityEditor, AppEntityEditorModal, AppEntityEditorModalOptions, AppForm, AppFormField, AppFormProvider, AppFormUtils, AppGestureConfig, AppGraphQLModule, AppHelpModal, AppIconComponent, AppIconModule, AppInMemoryTable, AppInstallUpgradeCard, AppListForm, AppLoadingSpinner, AppMenuModule, AppNullForm, AppPropertiesForm, AppTabEditor, AppTabEditorOptions, AppTable, AppTableDataSourceOptions, AppTableUtils, AppUserEventNotificationIcon, AppValidatorService, AppendToInputDirective, ArrayFilterPipe, ArrayFirstPipe, ArrayIncludesPipe, ArrayLengthPipe, ArrayPluckPipe, AudioProvider, AuthForm, AuthGuardService, AuthModal, AutoTitleDirective, AutocompleteTestPage, AutofocusDirective, Base58, BaseEntityService, BaseGraphqlService, BaseGraphqlServiceOptions, BaseReferential, Beans, CORE_CONFIG_OPTIONS, CORE_TESTING_PAGES, CellValueChangeListener, ChipsTestPage, Color, ColorScale, ComponentDirtyGuard, ConfigService, Configuration, CoreModule, CoreTestingModule, CryptoService, CsvUtils, DATE_ISO_PATTERN, DATE_UNIX_MS_TIMESTAMP, DATE_UNIX_TIMESTAMP, DEFAULT_MENU_SHOW_WHEN, DEFAULT_PAGE_SIZE, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLACEHOLDER_CHAR, DEFAULT_REQUIRED_COLUMNS, DateDiffDurationPipe, DateFormatPipe, DateFromNowPipe, DateTimeTestPage, DateUtils, Department, DepartmentToStringPipe, DragAndDropDirective, DurationPipe, ENTITIES_STORAGE_KEY_PREFIX, ENVIRONMENT, EmptyArrayPipe, EntitiesService, EntitiesStorage, EntitiesTableDataSource, Entity, EntityClass, EntityClasses, EntityFilter, EntityFilterUtils, EntityMetadataComponent, EntityStore, EntityUtils, Environment, ErrorCodes, EvenPipe, FileResponse, FileService, FileSizePipe, FilesUtils, FormArrayHelper, FormButtonsBarComponent, FormButtonsBarToken, FormErrorTranslatePipe, FormErrorTranslator, FormFieldValuesHolder, FormGetArrayPipe, FormGetControlPipe, FormGetGroupPipe, FormGetPipe, FormGetValuePipe, Fragments$1 as Fragments, GraphqlService, HAMMER_PRESS_TIME, HAMMER_TAP_TIME, HighlightPipe, HomePage, Hotkeys, HotkeysDialogComponent, IMAGE_DEFAULTS, ImagesUtils, InMemoryEntitiesService, IsLoginAccountPipe, IsNilOrBlankPipe, IsNotNilOrBlankPipe, IsNotOnFieldModePipe, IsOnFieldModePipe, Job, JobModule, JobProgression, JobProgressionComponent, JobProgressionService, JobProgressionServiceToken, JobProgressionTestService, JobProgressionTestingPage, JobTestingModule, JobUtils, KEYBOARD_HIDE_DELAY_MS, LAT_LONG_DEFAULT_MAX_DECIMALS, LAT_LONG_PATTERNS, LatLongFormatPipe, LatLongTestPage, LatitudeFormatPipe, LocalSettingsService, LongitudeFormatPipe, MINIFY_ENTITY_FOR_LOCAL_STORAGE, MINIFY_ENTITY_FOR_POD, MapGetPipe, MapKeysPipe, MapValuesPipe, MatAutocompleteConfigHolder, MatAutocompleteField, MatBadgeIconDirective, MatBooleanField, MatChipsField, MatDate, MatDateShort, MatDateTime, MatDuration, MatLatLongField, MatNumpadComponent, MatNumpadContainerComponent, MatNumpadContent, MatPaginatorI18n, MatStepperI18n, MatSwipeField, MaterialTestingModule, MathAbsPipe, MenuComponent, MenuItems, MenuOptions, MenuService, Message, MessageFilter, MessageForm, MessageModal, MessageModule, MessageService, MessageTypeList, MessageTypes, MimeTypes, ModalToolbarComponent, NetworkService, NgInitDirective, NgVarDirective, NotEmptyArrayPipe, NumberFormatPipe, NumpadDirective, OddPipe, PRIORITIZED_AUTHORITIES, PUBKEY_REGEXP, Peer, Person, PersonFilter, PersonFragments, PersonService, PersonToStringPipe, PersonUtils, PersonValidatorService, PlatformService, ProgressBarService, ProgressInterceptor, PropertyFormatPipe, PropertyGetPipe, RESERVED_END_COLUMNS, RESERVED_START_COLUMNS, Referential, ReferentialFilter, ReferentialRef, ReferentialUtils, ReferentialValidatorService, RegisterConfirmPage, ResizableComponent, ResizableDirective, ResizableModule, SETTINGS_DISPLAY_COLUMNS, SETTINGS_FILTER, SETTINGS_PAGE_SIZE, SETTINGS_SORTED_COLUMN, SETTINGS_STORAGE_KEY, SETTINGS_TRANSIENT_PROPERTIES, SHARED_MATERIAL_TESTING_PAGES, SHARED_TESTING_PAGES, SOCIAL_TESTING_PAGES, SPACE_PLACEHOLDER_CHAR, SelectPeerModal, ServerErrorCodes, SettingsPage, SharedAsyncValidators, SharedDirectivesModule, SharedFormArrayValidators, SharedFormGroupValidators, SharedHotkeysModule, SharedMatAutocompleteModule, SharedMatBadgeIconModule, SharedMatBooleanModule, SharedMatChipsModule, SharedMatDateTimeModule, SharedMatDurationModule, SharedMatLatLongModule, SharedMatNumpadModule, SharedMatSwipeModule, SharedMaterialModule, SharedModule, SharedPipesModule, SharedRoutingModule, SharedTestingModule, SharedTestsPage, SharedValidators, SocialErrorCodes, SocialModule, SocialModuleOptionsToken, SocialTestingModule, Software, StartableService, StatusById, StatusIds, StatusList, StrIncludesPipe, StrLengthPipe, SwipeTestPage, TableSelectColumnsComponent, TableTestPage, TableTestingModule, TextForm, TextPopover, TextPopoverTestingModule, TextPopoverTestingPage, ToStringPipe, Toasts, ToolbarComponent, ToolbarToken, TranslatablePipe, TranslateContextPipe, TranslateContextService, USER_EVENT_SERVICE, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEventModule, UserEventTestService, UserEventTestingModule, UserEventTestingPage, UserSettings, UsersPage, accountToString, adaptValueToControl, addValueInArray, arrayDistinct, arrayGroupBy, arraySize, asInputElement, canHaveFocus, capitalizeFirstLetter, chainPromises, changeCaseToUnderscore, clearValueInArray, copyEntity2Form, createPromiseEvent, createPromiseEventEmitter, departmentToString, departmentsToString, disableControls, emitPromiseEvent, entityToString, equals, equalsOrNil, escapeRegExp, fadeInAnimation, fadeInOutAnimation, filterFalse, filterNotNil, filterNumberInput, filterTrue, firstArrayValue, firstFalse, firstFalsePromise, firstNotNil, firstNotNilPromise, firstTrue, firstTruePromise, focusInput, focusNextInput, focusPreviousInput, formatLatitude, formatLongitude, fromDateISOString, fromScrollEndEvent, fromUnixMsTimestamp, fromUnixTimestamp, getCaretPosition, getColorContrast, getColorShade, getColorTint, getConnectionType, getControlFromPath, getFocusableInputElements, getFormErrors, getFormValueFromEntity, getProperty, getPropertyByPath, getPropertyByPathAsString, getRandomImage, hexToRgb, hexToRgbArray, isAndroid, isBlankString, isControlHasInput, isCordova, isEmptyArray, isIOS, isInputElement, isInstanceOf, isInt, isMobile, isNil, isNilOrBlank, isNilOrNaN, isNotEmptyArray, isNotNil, isNotNilBoolean, isNotNilOrBlank, isNotNilOrNaN, isNotNilString, isNumber, isNumberRange, isProgressEvent, isResponseEvent, isTouchUi, isWindows, joinProperties, joinPropertiesPath, logFormErrors, markAllAsTouched, markAsUntouched, markControlAsTouched, markFormGroupAsTouched, matchMedia, matchUpperCase, mergeLoadResult, mixHex, moment$5 as moment, moveInputCaretToSeparator, noTrailingSlash, notNilOrDefault, nullIfUndefined, parseLatitudeOrLongitude, propertiesPathComparator, propertyComparator, propertyPathComparator, referentialToString, referentialsToString, remove, removeAll, removeDiacritics, removeDuplicatesFromArray, removeEnd, removeValueInArray, replaceAll, resetCalculatedValue, resizeArray, rgbArrayToHex, rgbToHex, round, scrollFactory, selectInputContent, selectInputRange, setCalculatedValue, setTabIndex, sleep, slideInOutAnimation, slideUpDownAnimation, sort, splitById, splitByProperty, startsWithUpperCase, suggestFromArray, suggestFromStringArray, tabindexComparator, testUserAgent, toBoolean, toDateISOString, toDuration, toFloat, toInt, toNotNil, toNumber, trimEmptyToNull, tz, uncapitalizeFirstLetter, updateValueAndValidity, waitFor, waitForFalse, waitForTrue, waitIdle, waitWhilePending, ɵ0, CustomReuseStrategy as ɵa, MatNumpadDomService as ɵb, isFocusableElement as ɵc, RegisterForm as ɵd, AccountValidatorService as ɵe, RegisterModal as ɵf, UserSettingsValidatorService as ɵg, LocalSettingsValidatorService as ɵh, AppUpdateOfflineModeCard as ɵi, UserEventNotificationList as ɵj, JobProgressionList as ɵk, DateTestPage as ɵl, NumpadTestPage as ɵm, MatBadgeIconTestPage as ɵn, ToastTestingModule as ɵo, ToastTestingPage as ɵp };
29729
29823
  //# sourceMappingURL=sumaris-net.ngx-components.js.map