@sumaris-net/ngx-components 1.22.9 → 1.22.11-rc10

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 +752 -73
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/doc/changelog.md +6 -0
  6. package/esm2015/public_api.js +11 -2
  7. package/esm2015/src/app/core/menu/menu.component.js +2 -2
  8. package/esm2015/src/app/shared/events.js +8 -3
  9. package/esm2015/src/app/shared/services/entity-service.class.js +1 -1
  10. package/esm2015/src/app/social/job/testing/job-progression.testing.js +48 -0
  11. package/esm2015/src/app/social/job/testing/job-progression.testing.service.js +30 -0
  12. package/esm2015/src/app/social/job/testing/job.testing.module.js +25 -0
  13. package/esm2015/src/app/social/social.module.js +6 -1
  14. package/esm2015/src/app/social/social.testing.module.js +39 -0
  15. package/esm2015/src/app/social/user-event/notification/user-event-notification.icon.js +94 -0
  16. package/esm2015/src/app/social/user-event/notification/user-event-notification.list.js +131 -30
  17. package/esm2015/src/app/social/user-event/testing/user-event.testing.js +179 -0
  18. package/esm2015/src/app/social/user-event/testing/user-event.testing.module.js +25 -0
  19. package/esm2015/src/app/social/user-event/testing/user-event.testing.service.js +35 -6
  20. package/esm2015/src/app/social/user-event/user-event.model.js +1 -1
  21. package/esm2015/src/app/social/user-event/user-event.module.js +4 -4
  22. package/esm2015/src/app/social/user-event/user-event.service.js +74 -17
  23. package/fesm2015/sumaris-net.ngx-components.js +637 -63
  24. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  25. package/package.json +1 -1
  26. package/public_api.d.ts +8 -1
  27. package/src/app/shared/events.d.ts +1 -1
  28. package/src/app/shared/services/entity-service.class.d.ts +7 -0
  29. package/src/app/social/job/testing/job-progression.testing.d.ts +11 -0
  30. package/src/app/social/job/testing/job-progression.testing.service.d.ts +10 -0
  31. package/src/app/social/job/testing/job.testing.module.d.ts +2 -0
  32. package/src/app/social/social.testing.module.d.ts +4 -0
  33. package/src/app/social/user-event/notification/{user-event-notification.component.d.ts → user-event-notification.icon.d.ts} +3 -2
  34. package/src/app/social/user-event/notification/user-event-notification.list.d.ts +37 -12
  35. package/src/app/social/user-event/testing/user-event.testing.d.ts +23 -0
  36. package/src/app/social/user-event/testing/user-event.testing.module.d.ts +2 -0
  37. package/src/app/social/user-event/testing/user-event.testing.service.d.ts +4 -3
  38. package/src/app/social/user-event/user-event.model.d.ts +1 -0
  39. package/src/app/social/user-event/user-event.service.d.ts +16 -12
  40. package/src/theme/_ngx-components.scss +12 -0
  41. package/sumaris-net.ngx-components.metadata.json +1 -1
  42. package/esm2015/src/app/social/user-event/notification/user-event-notification.component.js +0 -89
@@ -32,10 +32,10 @@ import { MatAutocomplete, MatAutocompleteTrigger, MatAutocompleteModule, MAT_AUT
32
32
  import { __awaiter, __decorate } from 'tslib';
33
33
  import { Validators, NG_VALUE_ACCESSOR, FormGroupDirective, AbstractControl, FormGroup, FormArray, FormControl, ReactiveFormsModule, FormBuilder } from '@angular/forms';
34
34
  import { timer, merge, fromEvent, BehaviorSubject, Subscription, Subject, isObservable, from, of, noop as noop$9, Observable, defer, forkJoin, interval, combineLatest, EMPTY } from 'rxjs';
35
- import { filter, first, map, takeUntil, switchMap, tap, debounceTime, startWith, distinctUntilChanged, mergeMap, catchError, throttleTime, skip, bufferWhen } from 'rxjs/operators';
35
+ import { filter, first, map, takeUntil, switchMap, tap, debounceTime, startWith, distinctUntilChanged, mergeMap, catchError, throttleTime, skip, bufferWhen, take } from 'rxjs/operators';
36
36
  import { trigger, transition, style, animate, state } from '@angular/animations';
37
37
  import { TranslateService, TranslateModule } from '@ngx-translate/core';
38
- import { IonicModule, Platform, IonRouterOutlet, ModalController, PopoverController, IonicSafeString, createAnimation, ToastController, AlertController, IonicRouteStrategy, NavParams, MenuController, IonContent, IonInfiniteScroll } from '@ionic/angular';
38
+ import { IonicModule, Platform, IonRouterOutlet, ModalController, PopoverController, IonicSafeString, createAnimation, ToastController, AlertController, IonicRouteStrategy, NavParams, MenuController, IonContent, IonItem, IonInfiniteScroll } from '@ionic/angular';
39
39
  import * as momentImported from 'moment';
40
40
  import { isMoment } from 'moment';
41
41
  import { MomentDateAdapter, MatMomentDateModule } from '@angular/material-moment-adapter';
@@ -875,7 +875,7 @@ function emitPromiseEvent(emitter, eventType, initArg) {
875
875
  * @param element
876
876
  * @param threshold default to '15%'
877
877
  */
878
- function fromScrollEndEvent(element, threshold) {
878
+ function fromScrollEndEvent(element, threshold, dueTime) {
879
879
  threshold = threshold || '15%';
880
880
  let isEnd;
881
881
  // Listen using percentage
@@ -897,6 +897,11 @@ function fromScrollEndEvent(element, threshold) {
897
897
  else {
898
898
  throw new Error('Invalid argument \'threshold\'. Expected value unit: \'px\' or \'%\' ');
899
899
  }
900
+ // Check bottom reach, even if NO scroll event (e.g. when already reach the bottom)
901
+ if (dueTime > 0) {
902
+ return merge(fromEvent(element, 'scroll'), timer(dueTime))
903
+ .pipe(filter(() => isEnd()));
904
+ }
900
905
  return fromEvent(element, 'scroll')
901
906
  .pipe(filter(() => isEnd()));
902
907
  }
@@ -21485,7 +21490,7 @@ class MenuComponent {
21485
21490
  MenuComponent.decorators = [
21486
21491
  { type: Component, args: [{
21487
21492
  selector: 'app-menu',
21488
- 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 slot='header-bottom-right' -->\n <ion-col size=\"auto\">\n <ng-content select=\"[slot=header-bottom-right]\"></ng-content>\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",
21493
+ 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",
21489
21494
  animations: [fadeInAnimation],
21490
21495
  changeDetection: ChangeDetectionStrategy.OnPush,
21491
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)}}"]
@@ -25968,7 +25973,7 @@ class AbstractUserEventService extends BaseGraphqlService {
25968
25973
  this.network = network;
25969
25974
  this.translate = translate;
25970
25975
  this.options = options;
25971
- this.count$ = new BehaviorSubject(0);
25976
+ this._countSubject = new BehaviorSubject(0);
25972
25977
  this.listeners = [];
25973
25978
  this._subscriptions = new Subscription();
25974
25979
  this.queries = options.queries;
@@ -25976,8 +25981,8 @@ class AbstractUserEventService extends BaseGraphqlService {
25976
25981
  this.subscriptions = options.subscriptions || {};
25977
25982
  this._logPrefix = '[user-event-service] ';
25978
25983
  }
25979
- get userEventCount() {
25980
- return this.count$.asObservable();
25984
+ get countSubject() {
25985
+ return this._countSubject;
25981
25986
  }
25982
25987
  ngOnStart() {
25983
25988
  return __awaiter(this, void 0, void 0, function* () {
@@ -26003,7 +26008,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26003
26008
  watchAll(offset, size, sortBy, sortDirection, filter, options) {
26004
26009
  return this.watchPage({ offset, size, sortBy, sortDirection }, filter, options);
26005
26010
  }
26006
- watchPage(page, filter, options) {
26011
+ watchPage(page, filter, opts) {
26007
26012
  var _a;
26008
26013
  let now = this._debug && Date.now();
26009
26014
  if (!filter) {
@@ -26019,7 +26024,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26019
26024
  filter.recipients = [recipient];
26020
26025
  }
26021
26026
  }
26022
- const withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
26027
+ const withContent = (opts === null || opts === void 0 ? void 0 : opts.withContent) === true;
26023
26028
  return this.mutableWatchQuery({
26024
26029
  queryName: withContent ? 'LoadAllWithContent' : 'LoadAll',
26025
26030
  query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
@@ -26031,7 +26036,8 @@ class AbstractUserEventService extends BaseGraphqlService {
26031
26036
  },
26032
26037
  arrayFieldName: 'data',
26033
26038
  error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
26034
- fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || 'cache-first'
26039
+ fetchPolicy: (opts === null || opts === void 0 ? void 0 : opts.fetchPolicy) || 'cache-first',
26040
+ insertFilterFn: filter && filter.asFilterFn()
26035
26041
  })
26036
26042
  .pipe(map(res => {
26037
26043
  let data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this));
@@ -26039,14 +26045,69 @@ class AbstractUserEventService extends BaseGraphqlService {
26039
26045
  console.debug(`${this._logPrefix}${data.length} user events loaded in ${Date.now() - now}ms`);
26040
26046
  now = null;
26041
26047
  }
26042
- // Must re-order because of listenChanges result will add new event at the end
26048
+ // Must re-order because of listenAllChanges result will add new event at the end
26043
26049
  data = EntityUtils.sort(data, page.sortBy, page.sortDirection);
26044
- return {
26050
+ const result = {
26045
26051
  data,
26046
26052
  total: toNumber(res === null || res === void 0 ? void 0 : res.total, data.length)
26047
26053
  };
26054
+ // Add fetch more capability, if total was fetched
26055
+ if (isNotNil(res.total)) {
26056
+ const nextOffset = (page.offset || 0) + data.length;
26057
+ if (nextOffset < result.total) {
26058
+ result.fetchMore = (_) => this.loadPage(Object.assign(Object.assign({}, page), { offset: nextOffset }), filter, Object.assign(Object.assign({}, opts), { fetchPolicy: 'no-cache' }));
26059
+ }
26060
+ }
26061
+ return result;
26048
26062
  }));
26049
26063
  }
26064
+ loadPage(page, filter, opts) {
26065
+ var _a;
26066
+ return __awaiter(this, void 0, void 0, function* () {
26067
+ const now = this._debug && Date.now();
26068
+ if (!filter)
26069
+ filter = this.defaultFilter();
26070
+ console.debug(`${this._logPrefix}Loading user events...`, filter);
26071
+ filter = this.asFilter(filter);
26072
+ // Force recipient to current issuer, if not admin and not specified
26073
+ if (isEmptyArray(filter === null || filter === void 0 ? void 0 : filter.recipients) || !this.accountService.isAdmin()) {
26074
+ const recipient = this.defaultRecipient();
26075
+ if (!((_a = filter === null || filter === void 0 ? void 0 : filter.recipients) === null || _a === void 0 ? void 0 : _a.includes(recipient))) {
26076
+ console.warn('[user-events-service] Force user event filter.recipient=' + recipient);
26077
+ filter.recipients = [recipient];
26078
+ }
26079
+ }
26080
+ const withContent = (opts === null || opts === void 0 ? void 0 : opts.withContent) === true;
26081
+ const res = yield this.graphql.query({
26082
+ query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26083
+ variables: {
26084
+ page: Object.assign(Object.assign({ sortBy: 'creationDate' }, page), {
26085
+ // @ts-ignore
26086
+ sortDirection: (page.sortDirection || 'desc').toUpperCase() }),
26087
+ filter: filter && filter.asPodObject()
26088
+ },
26089
+ error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
26090
+ fetchPolicy: opts === null || opts === void 0 ? void 0 : opts.fetchPolicy
26091
+ });
26092
+ let data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this));
26093
+ if (now)
26094
+ console.debug(`${this._logPrefix}${data.length} user events loaded in ${Date.now() - now}ms`);
26095
+ // Must re-order because of listenAllChanges result will add new event at the end
26096
+ data = EntityUtils.sort(data, page.sortBy, page.sortDirection);
26097
+ const result = {
26098
+ data,
26099
+ total: toNumber(res === null || res === void 0 ? void 0 : res.total, data.length)
26100
+ };
26101
+ // Add fetch more capability, if total was fetched
26102
+ if (isNotNil(res.total)) {
26103
+ const nextOffset = (page.offset || 0) + data.length;
26104
+ if (nextOffset < result.total) {
26105
+ result.fetchMore = (_) => this.loadPage(Object.assign(Object.assign({}, page), { offset: nextOffset }), filter, opts);
26106
+ }
26107
+ }
26108
+ return result;
26109
+ });
26110
+ }
26050
26111
  add(entity) {
26051
26112
  // TODO set an id !!!!!!!!!!!!!!!!!!!!!!!!!
26052
26113
  entity = this.processUserEvent(entity);
@@ -26057,7 +26118,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26057
26118
  data: entity
26058
26119
  });
26059
26120
  // Update count
26060
- this.count$.next(this.count$.value + 1);
26121
+ this._countSubject.next(this._countSubject.value + 1);
26061
26122
  }
26062
26123
  count(filter, options) {
26063
26124
  var _a;
@@ -26094,6 +26155,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26094
26155
  filter = this.defaultFilter();
26095
26156
  // Apply last reset date as start date
26096
26157
  filter.startDate = this.resetCountDate;
26158
+ filter.excludeRead = true;
26097
26159
  filter = this.asFilter(filter);
26098
26160
  if (this._debug)
26099
26161
  console.debug(`${this._logPrefix}[WS] Listening count changes for user events with filter:`, filter);
@@ -26109,14 +26171,14 @@ class AbstractUserEventService extends BaseGraphqlService {
26109
26171
  if (total && this._debug)
26110
26172
  console.debug(`${this._logPrefix}Received new user events count:`, total);
26111
26173
  // update count
26112
- this.count$.next(total);
26174
+ this._countSubject.next(total);
26113
26175
  return total;
26114
26176
  }));
26115
26177
  }
26116
- listenChanges(filter, options) {
26178
+ listenAllChanges(filter, options) {
26117
26179
  var _a;
26118
- if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenChanges)) {
26119
- console.warn(`${this._logPrefix}Subscription query 'listenChanges' not provided, skip.`);
26180
+ if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenAllChanges)) {
26181
+ console.warn(`${this._logPrefix}Subscription query 'listenAllChanges' not provided, skip.`);
26120
26182
  return of();
26121
26183
  }
26122
26184
  if (!filter)
@@ -26126,7 +26188,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26126
26188
  if (this._debug)
26127
26189
  console.debug(`${this._logPrefix}[WS] Listening changes for user events with filter:`, filter);
26128
26190
  return this.graphql.subscribe({
26129
- query: this.subscriptions.listenChanges,
26191
+ query: this.subscriptions.listenAllChanges,
26130
26192
  fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
26131
26193
  variables: { filter: filter.asPodObject(), interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
26132
26194
  error: {
@@ -26255,7 +26317,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26255
26317
  this.listeners.push(listener);
26256
26318
  }
26257
26319
  resetCount() {
26258
- this.count$.next(undefined);
26320
+ this._countSubject.next(undefined);
26259
26321
  this.resetCountDate = moment$6();
26260
26322
  // restart listening count changes
26261
26323
  this.startListenCountChanges();
@@ -26268,7 +26330,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26268
26330
  if (this._debug)
26269
26331
  console.debug(`${this._logPrefix}Receiving user events count`, count);
26270
26332
  // Update count
26271
- this.count$.next(count);
26333
+ this._countSubject.next(count);
26272
26334
  // Then listen changes
26273
26335
  this.startListenCountChanges();
26274
26336
  });
@@ -26381,55 +26443,142 @@ AbstractUserEventService.ctorParameters = () => [
26381
26443
  ];
26382
26444
 
26383
26445
  class UserEventNotificationList {
26384
- constructor(cd, popoverController, userEventService) {
26446
+ constructor(cd, popoverController, settings, userEventService) {
26447
+ var _a;
26385
26448
  this.cd = cd;
26386
26449
  this.popoverController = popoverController;
26450
+ this.settings = settings;
26387
26451
  this.userEventService = userEventService;
26388
- this.debug = false;
26389
- this.userEvents = new BehaviorSubject(undefined);
26390
26452
  this.subscriptions = new Subscription();
26453
+ this._fetchingMore = false;
26454
+ this.debug = false;
26455
+ this.pageSize = 10;
26456
+ this.sortBy = 'creationDate';
26457
+ this.sortDirection = 'desc';
26458
+ this.enableInfiniteScroll = true;
26459
+ this.$items = new BehaviorSubject(undefined);
26460
+ this.$itemCount = new BehaviorSubject(undefined);
26461
+ this.mobile = ((_a = this.settings) === null || _a === void 0 ? void 0 : _a.mobile) || false;
26462
+ }
26463
+ get canFetchMore() {
26464
+ return this.enableInfiniteScroll && !!this._fetchMoreFn;
26391
26465
  }
26392
26466
  ngOnInit() {
26393
26467
  // Watch all user events
26394
- this.subscriptions.add(this.userEventService
26395
- .watchAll(0, 10, 'creationDate', "desc", undefined)
26396
- .subscribe(result => {
26397
- if (this.debug)
26398
- console.debug(`[user-event-notification-list] receiving ${result.total} user events`, result.data);
26399
- this.userEvents.next(result.data);
26400
- this.markForCheck();
26401
- }));
26402
- // Listen changes
26403
- this.subscriptions.add(this.userEventService.listenChanges(undefined)
26404
- .subscribe(data => {
26405
- if (this.debug)
26406
- console.debug(`[user-event-notification-list] receiving ${data.length} new user events`, data);
26407
- }));
26468
+ if (this.userEventService) {
26469
+ this.subscriptions.add(this.userEventService
26470
+ .watchAll(0, this.pageSize, this.sortBy, this.sortDirection, this.filter)
26471
+ .subscribe(result => {
26472
+ var _a;
26473
+ if (this.debug)
26474
+ console.debug(`[user-event-notification-list] receiving ${result.total} user events`, result.data);
26475
+ this.$items.next(result.data);
26476
+ this.$itemCount.next(result.total || ((_a = result.data) === null || _a === void 0 ? void 0 : _a.length) || 0);
26477
+ this._fetchMoreFn = result.fetchMore;
26478
+ this.markForCheck();
26479
+ }));
26480
+ // Listen changes
26481
+ this.subscriptions.add(this.userEventService.listenAllChanges(undefined)
26482
+ .subscribe(data => {
26483
+ if (this.debug)
26484
+ console.debug(`[user-event-notification-list] receiving ${data.length} new user events`, data);
26485
+ }));
26486
+ }
26408
26487
  }
26409
26488
  ngOnDestroy() {
26410
26489
  this.subscriptions.unsubscribe();
26411
26490
  }
26412
- read(event, userEvent) {
26491
+ click(event, userEvent) {
26492
+ if (!userEvent)
26493
+ return; // Skip
26494
+ // MarkAsRead
26495
+ this.markAsRead(event, userEvent);
26496
+ // Get the default action (if any)
26497
+ const defaultAction = ((userEvent === null || userEvent === void 0 ? void 0 : userEvent.actions) || []).find(a => a.default);
26498
+ if (defaultAction) {
26499
+ this.executeAction(event, defaultAction, userEvent);
26500
+ }
26501
+ }
26502
+ isDefaultAction(action) {
26503
+ return action && action.default || false;
26504
+ }
26505
+ markAsRead(event, userEvent) {
26413
26506
  var _a;
26414
26507
  if (userEvent === null || userEvent === void 0 ? void 0 : userEvent.readDate)
26415
26508
  return;
26416
26509
  (_a = this.readEvent) === null || _a === void 0 ? void 0 : _a.emit(userEvent);
26417
26510
  }
26418
- readAll(event) {
26511
+ markAllAsRead(event) {
26419
26512
  var _a;
26420
- const unreadUserEvents = (this.userEvents.value || []).filter(value => !value.readDate);
26513
+ const unreadUserEvents = (this.$items.value || []).filter(value => !value.readDate);
26421
26514
  if (!unreadUserEvents.length)
26422
26515
  return;
26423
26516
  (_a = this.readEvents) === null || _a === void 0 ? void 0 : _a.emit(unreadUserEvents);
26424
26517
  }
26425
- executeAction(action, userEvent) {
26426
- // Execute then close popover
26427
- action.executeAction(userEvent);
26428
- this.dismiss();
26518
+ executeAction(event, action, userEvent) {
26519
+ return __awaiter(this, void 0, void 0, function* () {
26520
+ if (event === null || event === void 0 ? void 0 : event.defaultPrevented)
26521
+ return; // Skip if prevented
26522
+ // Disable default action (.e.g avoid to call click() function)
26523
+ if (event)
26524
+ event.preventDefault();
26525
+ // Execute then close popover
26526
+ try {
26527
+ const res = action.executeAction(userEvent);
26528
+ this.dismiss();
26529
+ if (res instanceof Promise)
26530
+ yield res;
26531
+ }
26532
+ catch (err) {
26533
+ console.error(err);
26534
+ }
26535
+ });
26429
26536
  }
26430
26537
  dismiss() {
26431
26538
  this.popoverController.dismiss();
26432
26539
  }
26540
+ fetchMore(event) {
26541
+ var _a;
26542
+ return __awaiter(this, void 0, void 0, function* () {
26543
+ if (!this._fetchMoreFn || this._fetchingMore)
26544
+ return;
26545
+ console.debug('[user-event-notification-list] Fetching more notifications...', event);
26546
+ this._fetchingMore = true;
26547
+ try {
26548
+ const result = yield this._fetchMoreFn();
26549
+ let data = [
26550
+ ...(this.$items.value || []),
26551
+ ...result.data
26552
+ ];
26553
+ // Remove duplication (e.g. when new user event was added by subscription)
26554
+ data = removeDuplicatesFromArray(data, 'id');
26555
+ this.$items.next(data);
26556
+ this.$itemCount.next(result.total || ((_a = result.data) === null || _a === void 0 ? void 0 : _a.length) || 0);
26557
+ this._fetchMoreFn = result.fetchMore;
26558
+ }
26559
+ catch (err) {
26560
+ console.error(err);
26561
+ this._fetchMoreFn = undefined;
26562
+ }
26563
+ finally {
26564
+ this.markForCheck();
26565
+ this._fetchingMore = false;
26566
+ }
26567
+ });
26568
+ }
26569
+ _initInfiniteScroll(threshold) {
26570
+ return __awaiter(this, void 0, void 0, function* () {
26571
+ if (this._fetchMoreSubscription)
26572
+ this._fetchMoreSubscription.unsubscribe();
26573
+ threshold = threshold || (this.mobile ? '15%' : '2%');
26574
+ yield waitFor(() => !!this.ionContent);
26575
+ const panel = yield this.ionContent.getScrollElement();
26576
+ // 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*/)
26578
+ .subscribe(() => this.fetchMore());
26579
+ this.subscriptions.add(this._fetchMoreSubscription);
26580
+ });
26581
+ }
26433
26582
  markForCheck() {
26434
26583
  this.cd.markForCheck();
26435
26584
  }
@@ -26437,24 +26586,33 @@ class UserEventNotificationList {
26437
26586
  UserEventNotificationList.decorators = [
26438
26587
  { type: Component, args: [{
26439
26588
  selector: 'app-user-event-notification-list',
26440
- template: "\n<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n <ion-col class=\"top-action\" *ngIf=\"userEvents|async|isNotEmptyArray\">\n <ion-text color=\"primary\">\n <a (click)=\"readAll($event)\">{{'SOCIAL.USER_EVENT.NOTIFICATION.READ_ALL' | translate}}</a>\n </ion-text>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"userEvents|async|isEmptyArray\" lines=\"none\">\n <ion-text color=\"dark\" class=\"text-italic\">{{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}</ion-text>\n </ion-item>\n <ion-item\n *ngFor=\"let userEvent of userEvents | async\"\n (click)=\"read($event, userEvent)\"\n >\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"userEvent.avatar; else avatarIcon\" src=\"{{ userEvent.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"userEvent.avatarIcon\"\n [ref]=\"userEvent.avatarIcon\"\n height=\"40\"\n width=\"40\"\n ></app-icon>\n </ng-template>\n\n </ion-avatar>\n\n <ion-grid class=\"ion-no-margin ion-no-padding message\">\n <ion-row>\n <ion-col>\n <p [class.unread]=\"!userEvent.readDate\" [innerHTML]=\"userEvent.message\"></p>\n </ion-col>\n </ion-row>\n <ion-row *ngIf=\"userEvent.actions?.length\">\n <ion-col>\n <span *ngFor=\"let action of userEvent.actions\" class=\"action\">\n <a (click)=\"executeAction(action, userEvent)\">\n <app-icon *ngIf=\"action.iconRef\" slot=\"start\" height=\"20\" width=\"20\" [ref]=\"action.iconRef\"></app-icon>\n {{ action.name }}\n </a>\n </span>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <app-icon\n *ngIf=\"userEvent.icon\"\n [ref]=\"userEvent.icon\"\n height=\"16\"\n width=\"16\"\n style=\"vertical-align: sub; margin-right: 3px\"\n ></app-icon>\n <small>\n <span>{{userEvent.creationDate|dateFromNow}}</span>\n <span style=\"color: gray\">{{ ' | ' + (userEvent.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n <ion-row class=\"ion-list-footer column\">\n </ion-row>\n\n</ion-list>\n",
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",
26441
26590
  changeDetection: ChangeDetectionStrategy.OnPush,
26442
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.unread{font-weight:700}.message{font-size:.9em}.message p{margin-top:5px;margin-bottom:5px}.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}.action a{margin-right:10px;cursor:pointer}.action app-icon{vertical-align:middle}"]
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}"]
26443
26592
  },] }
26444
26593
  ];
26445
26594
  UserEventNotificationList.ctorParameters = () => [
26446
26595
  { type: ChangeDetectorRef },
26447
26596
  { type: PopoverController },
26597
+ { type: LocalSettingsService, decorators: [{ type: Optional }] },
26448
26598
  { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [USER_EVENT_SERVICE,] }] }
26449
26599
  ];
26450
26600
  UserEventNotificationList.propDecorators = {
26451
26601
  debug: [{ type: Input }],
26602
+ mobile: [{ type: Input }],
26452
26603
  titleI18n: [{ type: Input }],
26604
+ pageSize: [{ type: Input }],
26605
+ sortBy: [{ type: Input }],
26606
+ sortDirection: [{ type: Input }],
26607
+ filter: [{ type: Input }],
26608
+ enableInfiniteScroll: [{ type: Input }],
26453
26609
  readEvent: [{ type: Output }],
26454
- readEvents: [{ type: Output }]
26610
+ readEvents: [{ type: Output }],
26611
+ ionContent: [{ type: ViewChild, args: [IonContent,] }],
26612
+ ionItems: [{ type: ViewChildren, args: [IonItem,] }]
26455
26613
  };
26456
26614
 
26457
- class UserEventNotificationComponent {
26615
+ class AppUserEventNotificationIcon {
26458
26616
  constructor(userEventService, accountService, popoverController) {
26459
26617
  this.userEventService = userEventService;
26460
26618
  this.accountService = accountService;
@@ -26462,13 +26620,17 @@ class UserEventNotificationComponent {
26462
26620
  this.debug = false;
26463
26621
  this.titleI18n = 'SOCIAL.USER_EVENT.NOTIFICATION.TITLE';
26464
26622
  this.disabled = false;
26623
+ this.filter = null;
26465
26624
  this._logPrefix = '[user-event-notification] ';
26466
26625
  this._readEvent = new EventEmitter();
26467
26626
  this._readEvents = new EventEmitter();
26468
26627
  }
26469
- get count() {
26470
- var _a;
26471
- return (_a = this.userEventService) === null || _a === void 0 ? void 0 : _a.userEventCount.pipe(map(value => value === 0 ? undefined : value));
26628
+ get countChanges() {
26629
+ if (!this.userEventService)
26630
+ return of();
26631
+ return this.userEventService
26632
+ .countSubject
26633
+ .pipe(map(value => value === 0 ? undefined : value));
26472
26634
  }
26473
26635
  ngOnInit() {
26474
26636
  return __awaiter(this, void 0, void 0, function* () {
@@ -26505,7 +26667,7 @@ class UserEventNotificationComponent {
26505
26667
  keyboardClose: true,
26506
26668
  event,
26507
26669
  translucent: true,
26508
- cssClass: 'popover-large'
26670
+ cssClass: 'popover-large popover-notifications'
26509
26671
  });
26510
26672
  yield popover.present();
26511
26673
  });
@@ -26516,23 +26678,23 @@ class UserEventNotificationComponent {
26516
26678
  }
26517
26679
  }
26518
26680
  }
26519
- UserEventNotificationComponent.decorators = [
26681
+ AppUserEventNotificationIcon.decorators = [
26520
26682
  { type: Component, args: [{
26521
- selector: 'app-user-event-notification-component',
26522
- template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n [matBadge]=\"count | async\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n >notifications\n </mat-icon>\n</button>\n\n",
26523
- changeDetection: ChangeDetectionStrategy.OnPush,
26524
- styles: [""]
26683
+ selector: 'app-user-event-notification-icon',
26684
+ template: "<button\n #button\n mat-icon-button\n [title]=\"titleI18n | translate\"\n [disabled]=\"disabled\"\n (click)=\"showList($event)\"\n>\n <mat-icon\n [matBadge]=\"countChanges | async\"\n matBadgeColor=\"accent\"\n matBadgeSize=\"small\"\n matBadgePosition=\"above after\"\n >notifications\n </mat-icon>\n</button>\n\n",
26685
+ changeDetection: ChangeDetectionStrategy.OnPush
26525
26686
  },] }
26526
26687
  ];
26527
- UserEventNotificationComponent.ctorParameters = () => [
26688
+ AppUserEventNotificationIcon.ctorParameters = () => [
26528
26689
  { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [USER_EVENT_SERVICE,] }] },
26529
26690
  { type: AccountService },
26530
26691
  { type: PopoverController }
26531
26692
  ];
26532
- UserEventNotificationComponent.propDecorators = {
26693
+ AppUserEventNotificationIcon.propDecorators = {
26533
26694
  debug: [{ type: Input }],
26534
26695
  titleI18n: [{ type: Input }],
26535
- disabled: [{ type: Input }]
26696
+ disabled: [{ type: Input }],
26697
+ filter: [{ type: Input }]
26536
26698
  };
26537
26699
 
26538
26700
  class UserEventModule {
@@ -26545,11 +26707,11 @@ UserEventModule.decorators = [
26545
26707
  AppIconModule
26546
26708
  ],
26547
26709
  declarations: [
26548
- UserEventNotificationComponent,
26710
+ AppUserEventNotificationIcon,
26549
26711
  UserEventNotificationList
26550
26712
  ],
26551
26713
  exports: [
26552
- UserEventNotificationComponent
26714
+ AppUserEventNotificationIcon
26553
26715
  ]
26554
26716
  },] }
26555
26717
  ];
@@ -27093,6 +27255,11 @@ SocialModule.decorators = [
27093
27255
  JobModule,
27094
27256
  MessageModule
27095
27257
  ],
27258
+ exports: [
27259
+ UserEventModule,
27260
+ JobModule,
27261
+ MessageModule
27262
+ ]
27096
27263
  },] }
27097
27264
  ];
27098
27265
 
@@ -29145,11 +29312,418 @@ CoreTestingModule.decorators = [
29145
29312
  },] }
29146
29313
  ];
29147
29314
 
29315
+ class JobProgressionTestService {
29316
+ listenChanges(id, options) {
29317
+ return interval(100).pipe(take(111), map(value => {
29318
+ if (value <= 10) {
29319
+ return {
29320
+ id: id,
29321
+ name: `Job #${id}`,
29322
+ current: 0,
29323
+ total: 0,
29324
+ message: `Progression pending`
29325
+ };
29326
+ }
29327
+ value = value - 10;
29328
+ return {
29329
+ id: id,
29330
+ name: `Job #${id}`,
29331
+ current: value,
29332
+ total: 100,
29333
+ message: `Progression ${value}/100`
29334
+ };
29335
+ }));
29336
+ }
29337
+ }
29338
+ JobProgressionTestService.decorators = [
29339
+ { type: Injectable }
29340
+ ];
29341
+
29342
+ class JobProgressionTestingPage {
29343
+ constructor() {
29344
+ this.nJob = 0;
29345
+ this.options = {
29346
+ autoHide: true
29347
+ };
29348
+ this.job = new JobProgression();
29349
+ this.job.id = 0;
29350
+ this.job.name = 'test';
29351
+ this.job.current = 0;
29352
+ this.job.total = 100;
29353
+ }
29354
+ incrementJob(value) {
29355
+ this.job.current = Math.max(0, this.job.current + value);
29356
+ this.job.message = `Fake progression (very long message very long message very long message very long message) ${this.job.current}/100`;
29357
+ if (this.job.current > this.job.total) {
29358
+ this.jobProgression.removeJob(0);
29359
+ this.job.current = 0;
29360
+ }
29361
+ else if (!this.jobProgression.getProgression(0)) {
29362
+ this.jobProgression.jobProgressions.push(this.job);
29363
+ }
29364
+ this.jobProgression.updateValue();
29365
+ }
29366
+ addJob() {
29367
+ // Add fake job
29368
+ this.nJob++;
29369
+ this.jobProgression.addJob(this.nJob);
29370
+ }
29371
+ }
29372
+ JobProgressionTestingPage.decorators = [
29373
+ { type: Component, args: [{
29374
+ selector: 'job-progression-testing',
29375
+ template: "<ion-toolbar color=\"primary\">\n <ion-title>Job progression</ion-title>\n</ion-toolbar>\n\n<ion-content class=\"ion-padding\">\n\n <app-job-progression #jobProgression [debug]=\"true\" [options]=\"options\" ></app-job-progression>\n\n <p>\n <ion-button (click)=\"incrementJob(10)\">\n +10\n </ion-button>\n <ion-button (click)=\"incrementJob(-10)\">\n -10\n </ion-button>\n </p>\n <p>\n <ion-button (click)=\"addJob()\">Add Job</ion-button>\n </p>\n</ion-content>\n",
29376
+ providers: [
29377
+ { provide: JobProgressionServiceToken, useClass: JobProgressionTestService }
29378
+ ]
29379
+ },] }
29380
+ ];
29381
+ JobProgressionTestingPage.ctorParameters = () => [];
29382
+ JobProgressionTestingPage.propDecorators = {
29383
+ jobProgression: [{ type: ViewChild, args: ['jobProgression',] }]
29384
+ };
29385
+
29386
+ class JobTestingModule {
29387
+ }
29388
+ JobTestingModule.decorators = [
29389
+ { type: NgModule, args: [{
29390
+ imports: [
29391
+ CommonModule,
29392
+ TranslateModule.forChild(),
29393
+ SharedModule,
29394
+ JobModule
29395
+ ],
29396
+ declarations: [
29397
+ JobProgressionTestingPage
29398
+ ],
29399
+ exports: [
29400
+ JobProgressionTestingPage
29401
+ ]
29402
+ },] }
29403
+ ];
29404
+
29405
+ class UserEventTestService extends AbstractUserEventService {
29406
+ constructor(graphql, accountService, network, translate, environment) {
29407
+ super(graphql, accountService, network, translate, {
29408
+ queries: {
29409
+ loadAll: null,
29410
+ loadAllWithContent: null
29411
+ },
29412
+ production: environment === null || environment === void 0 ? void 0 : environment.production
29413
+ });
29414
+ this.graphql = graphql;
29415
+ this.accountService = accountService;
29416
+ this.network = network;
29417
+ this.translate = translate;
29418
+ this.environment = environment;
29419
+ this.userEvents = [];
29420
+ }
29421
+ fromObject(source) {
29422
+ return UserEvent.fromObject(source);
29423
+ }
29424
+ 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);
29432
+ }
29433
+ asFilter(filter) {
29434
+ return filter;
29435
+ }
29436
+ count(filter, options) {
29437
+ return Promise.resolve(this.userEvents.length);
29438
+ }
29439
+ delete(entity) {
29440
+ return Promise.resolve(undefined);
29441
+ }
29442
+ deleteAll(data, opts) {
29443
+ return Promise.resolve(undefined);
29444
+ }
29445
+ listenAllChanges(filter, options) {
29446
+ return of();
29447
+ }
29448
+ save(entity, options) {
29449
+ 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));
29451
+ Object.assign(toSave, entity);
29452
+ return entity;
29453
+ }
29454
+ saveAll(data, opts) {
29455
+ return __awaiter(this, void 0, void 0, function* () {
29456
+ for (const entity of (data || [])) {
29457
+ yield this.save(entity);
29458
+ }
29459
+ return Promise.resolve(this.userEvents);
29460
+ });
29461
+ }
29462
+ 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);
29475
+ }
29476
+ loadAll(offset, size, sortBy, sortDirection, filter, opts) {
29477
+ 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;
29480
+ const res = { data, total };
29481
+ // Must re-order because of listenChanges result will add new event at the end
29482
+ data = EntityUtils.sort(data, sortBy, sortDirection);
29483
+ // Add fetch more
29484
+ const nextOffset = offset + data.length;
29485
+ if (nextOffset < res.total) {
29486
+ res.fetchMore = (_) => this.loadAll(nextOffset, size, sortBy, sortDirection, filter, Object.assign(Object.assign({}, opts), { fetchPolicy: 'no-cache' }));
29487
+ }
29488
+ return Promise.resolve(res);
29489
+ }
29490
+ }
29491
+ UserEventTestService.decorators = [
29492
+ { type: Injectable }
29493
+ ];
29494
+ UserEventTestService.ctorParameters = () => [
29495
+ { type: GraphqlService },
29496
+ { type: AccountService },
29497
+ { type: NetworkService },
29498
+ { type: TranslateService },
29499
+ { type: Environment, decorators: [{ type: Optional }, { type: Inject, args: [ENVIRONMENT,] }] }
29500
+ ];
29501
+
29502
+ const moment$a = momentImported;
29503
+ class UserEventTestingPage {
29504
+ constructor(userEventService, router, alertController, translateService) {
29505
+ this.userEventService = userEventService;
29506
+ this.router = router;
29507
+ this.alertController = alertController;
29508
+ this.translateService = translateService;
29509
+ userEventService.registerListener({
29510
+ accept: (userEvent) => { return true; },
29511
+ onReceived: (userEvent) => {
29512
+ this.customize(userEvent);
29513
+ return userEvent;
29514
+ }
29515
+ });
29516
+ userEventService.registerListener({
29517
+ accept: (userEvent) => { return userEvent.level == "DEBUG"; },
29518
+ onRead: (userEvent) => { this.showMessage("debug message read "); }
29519
+ });
29520
+ }
29521
+ customize(userEvent) {
29522
+ // Choose avatarIcon
29523
+ switch (userEvent.level) {
29524
+ case 'ERROR':
29525
+ userEvent.avatarIcon = { icon: 'close-outline', color: 'danger' };
29526
+ break;
29527
+ case 'WARNING':
29528
+ userEvent.avatarIcon = { icon: 'warning-outline', color: 'warning' };
29529
+ break;
29530
+ case 'INFO':
29531
+ userEvent.avatarIcon = { icon: 'information-circle-outline' };
29532
+ break;
29533
+ case 'DEBUG':
29534
+ userEvent.avatarIcon = { icon: 'cog', color: "medium" };
29535
+ break;
29536
+ }
29537
+ // Choose icon
29538
+ switch (userEvent.type) {
29539
+ case 'message':
29540
+ userEvent.icon = { matIcon: 'inbox', color: 'accent' };
29541
+ break;
29542
+ case 'upload':
29543
+ userEvent.icon = { matIcon: 'file_upload' };
29544
+ break;
29545
+ case 'download':
29546
+ userEvent.icon = { matIcon: 'file_download' };
29547
+ break;
29548
+ }
29549
+ }
29550
+ addNotification() {
29551
+ this.userEventService.add(UserEvent.fromObject({
29552
+ issuer: 'system',
29553
+ recipient: 'me',
29554
+ type: 'message',
29555
+ level: 'INFO',
29556
+ message: 'message test message test message test message test message test message test message test message test',
29557
+ creationDate: moment$a(),
29558
+ }));
29559
+ }
29560
+ addError() {
29561
+ this.userEventService.add(UserEvent.fromObject({
29562
+ issuer: 'system',
29563
+ recipient: 'me',
29564
+ type: 'upload',
29565
+ level: 'ERROR',
29566
+ message: 'message error',
29567
+ creationDate: moment$a(),
29568
+ }));
29569
+ }
29570
+ addWarning() {
29571
+ this.userEventService.add(UserEvent.fromObject({
29572
+ issuer: 'system',
29573
+ recipient: 'me',
29574
+ type: 'download',
29575
+ level: 'WARNING',
29576
+ message: 'message warning',
29577
+ creationDate: moment$a(),
29578
+ }));
29579
+ }
29580
+ addDebug() {
29581
+ this.userEventService.add(UserEvent.fromObject({
29582
+ issuer: 'system',
29583
+ recipient: 'me',
29584
+ type: 'debug',
29585
+ level: 'DEBUG',
29586
+ message: 'message DEBUG',
29587
+ creationDate: moment$a(),
29588
+ }));
29589
+ }
29590
+ addNotificationWithLink() {
29591
+ this.userEventService.add(UserEvent.fromObject({
29592
+ issuer: 'system',
29593
+ recipient: 'me',
29594
+ type: 'message',
29595
+ level: 'INFO',
29596
+ message: 'message with link',
29597
+ creationDate: moment$a(),
29598
+ actions: [{
29599
+ name: 'click here',
29600
+ iconRef: {
29601
+ icon: 'arrow-forward-outline'
29602
+ },
29603
+ executeAction: event => { this.router.navigateByUrl('/'); }
29604
+ }]
29605
+ }));
29606
+ }
29607
+ addNotificationWithAction() {
29608
+ this.userEventService.add(UserEvent.fromObject({
29609
+ issuer: 'system',
29610
+ recipient: 'me',
29611
+ type: 'message',
29612
+ level: 'INFO',
29613
+ message: 'message with action',
29614
+ creationDate: moment$a(),
29615
+ actions: [
29616
+ {
29617
+ name: 'click here',
29618
+ iconRef: {
29619
+ icon: 'arrow-forward-outline',
29620
+ color: 'warning'
29621
+ },
29622
+ executeAction: event => { this.showMessage('action 1'); }
29623
+ },
29624
+ {
29625
+ name: 'click here 2',
29626
+ iconRef: {
29627
+ matIcon: 'settings_applications',
29628
+ color: 'secondary'
29629
+ },
29630
+ executeAction: event => { this.showMessage('action 2'); }
29631
+ }
29632
+ ]
29633
+ }));
29634
+ }
29635
+ addNotificationWithDefaultAction() {
29636
+ this.userEventService.add(UserEvent.fromObject({
29637
+ issuer: 'system',
29638
+ recipient: 'me',
29639
+ type: 'message',
29640
+ level: 'INFO',
29641
+ message: 'message with action',
29642
+ creationDate: moment$a(),
29643
+ actions: [
29644
+ {
29645
+ default: true,
29646
+ name: 'default',
29647
+ executeAction: event => { this.showMessage('default action'); }
29648
+ }
29649
+ ]
29650
+ }));
29651
+ }
29652
+ showMessage(text) {
29653
+ return Alerts.showError(text, this.alertController, this.translateService);
29654
+ }
29655
+ }
29656
+ UserEventTestingPage.decorators = [
29657
+ { type: Component, args: [{
29658
+ 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"
29660
+ },] }
29661
+ ];
29662
+ UserEventTestingPage.ctorParameters = () => [
29663
+ { type: UserEventTestService, decorators: [{ type: Inject, args: [USER_EVENT_SERVICE,] }] },
29664
+ { type: Router },
29665
+ { type: AlertController },
29666
+ { type: TranslateService }
29667
+ ];
29668
+ UserEventTestingPage.propDecorators = {
29669
+ notification: [{ type: ViewChild, args: ['notification',] }]
29670
+ };
29671
+
29672
+ class UserEventTestingModule {
29673
+ }
29674
+ UserEventTestingModule.decorators = [
29675
+ { type: NgModule, args: [{
29676
+ imports: [
29677
+ CommonModule,
29678
+ TranslateModule.forChild(),
29679
+ SharedModule,
29680
+ UserEventModule
29681
+ ],
29682
+ declarations: [
29683
+ UserEventTestingPage
29684
+ ],
29685
+ exports: [
29686
+ UserEventTestingPage
29687
+ ]
29688
+ },] }
29689
+ ];
29690
+
29691
+ const SOCIAL_TESTING_PAGES = [
29692
+ { label: 'Social components', divider: true },
29693
+ { label: 'User event', page: '/testing/social/user-event' },
29694
+ { label: 'Job progression', page: '/testing/social/job-progression' }
29695
+ ];
29696
+ const routes$6 = [
29697
+ {
29698
+ path: 'job-progression',
29699
+ pathMatch: 'full',
29700
+ component: JobProgressionTestingPage
29701
+ },
29702
+ {
29703
+ path: 'user-event',
29704
+ pathMatch: 'full',
29705
+ component: UserEventTestingPage
29706
+ },
29707
+ ];
29708
+ class SocialTestingModule {
29709
+ }
29710
+ SocialTestingModule.decorators = [
29711
+ { type: NgModule, args: [{
29712
+ imports: [
29713
+ CommonModule,
29714
+ TranslateModule.forChild(),
29715
+ RouterModule.forChild(routes$6),
29716
+ JobTestingModule,
29717
+ UserEventTestingModule
29718
+ ],
29719
+ },] }
29720
+ ];
29721
+
29148
29722
  // Environment
29149
29723
 
29150
29724
  /**
29151
29725
  * Generated bundle index. Do not edit.
29152
29726
  */
29153
29727
 
29154
- 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, 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, 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, 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, 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, UserEventNotificationComponent, 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 };
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 };
29155
29729
  //# sourceMappingURL=sumaris-net.ngx-components.js.map