@sumaris-net/ngx-components 1.21.0-beta2 → 1.21.0-beta22

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 (26) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +478 -156
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +1 -1
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/esm2015/src/app/core/menu/menu.component.js +2 -9
  6. package/esm2015/src/app/social/job/job.service.js +1 -2
  7. package/esm2015/src/app/social/user-event/notification/user-event-notification.component.js +23 -31
  8. package/esm2015/src/app/social/user-event/notification/user-event-notification.list.js +47 -8
  9. package/esm2015/src/app/social/user-event/testing/user-event.testing.service.js +73 -0
  10. package/esm2015/src/app/social/user-event/user-event.model.js +1 -1
  11. package/esm2015/src/app/social/user-event/user-event.module.js +6 -1
  12. package/esm2015/src/app/social/user-event/user-event.service.js +201 -63
  13. package/esm2015/sumaris-net.ngx-components.js +8 -7
  14. package/fesm2015/sumaris-net.ngx-components.js +328 -103
  15. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/app/social/user-event/notification/user-event-notification.component.d.ts +5 -8
  18. package/src/app/social/user-event/notification/user-event-notification.list.d.ts +18 -8
  19. package/src/app/social/user-event/testing/user-event.testing.service.d.ts +35 -0
  20. package/src/app/social/user-event/user-event.model.d.ts +1 -1
  21. package/src/app/social/user-event/user-event.service.d.ts +31 -11
  22. package/src/assets/i18n/en.json +2 -1
  23. package/src/assets/i18n/fr.json +2 -1
  24. package/src/theme/_ngx-components.scss +1 -0
  25. package/sumaris-net.ngx-components.d.ts +7 -6
  26. package/sumaris-net.ngx-components.metadata.json +1 -1
@@ -21172,9 +21172,6 @@ class MenuComponent {
21172
21172
  this._subscription = new Subscription();
21173
21173
  this.loading = true;
21174
21174
  this.isLogin = false;
21175
- // showUserEventNotification: boolean;
21176
- // showJobProgression: boolean;
21177
- // jobProgressionOptions: JobProgressionOptions;
21178
21175
  this.$items = new BehaviorSubject(undefined);
21179
21176
  this.id = 'menu';
21180
21177
  this.menuId = 'left';
@@ -21188,10 +21185,6 @@ class MenuComponent {
21188
21185
  this.splitPane.when = yield firstNotNilPromise(this.menuService.splitPaneWhen);
21189
21186
  // Wait platform started
21190
21187
  yield this.platformService.ready();
21191
- // Init social options
21192
- // this.showUserEventNotification = toBoolean(this.socialModuleOptions?.showUserEventNotification, false);
21193
- // this.showJobProgression = toBoolean(this.socialModuleOptions?.showJobProgression, false);
21194
- // this.jobProgressionOptions = this.socialModuleOptions?.jobProgressionOptions;
21195
21188
  // Listen to menu service event
21196
21189
  this.menuService.splitPaneWhen
21197
21190
  .subscribe((value) => this.setSplitPaneWhen(value));
@@ -21438,7 +21431,7 @@ class MenuComponent {
21438
21431
  MenuComponent.decorators = [
21439
21432
  { type: Component, args: [{
21440
21433
  selector: 'app-menu',
21441
- template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n<!-- todo ajouter ici les 2 composants du module social -->\n\n </ion-row>\n </ion-grid>\n\n </ion-toolbar>\n\n <!-- User not logged -->\n <ng-template #notLogin>\n <mat-toolbar class=\"ion-padding\" @fadeInAnimation\n style=\"height: unset; display: block; margin: auto; text-align: center;\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"150px;\">\n <span *ngIf=\"!logo\" style=\"width: 150px\">{{appName}}</span>\n </mat-toolbar>\n </ng-template>\n </ion-header>\n\n <ion-content [class.has-user-header]=\"isLogin\">\n\n <ion-list lines=\"none\">\n <ion-menu-toggle auto-hide=\"false\"\n [class.flex-spacer]=\"item.cssClass == 'flex-spacer'\"\n *ngFor=\"let item of $items | async\">\n\n <!-- link -->\n <ion-item *ngIf=\"!loading && item.path\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n routerLinkActive=\"selected\"\n [routerLinkActiveOptions]=\"{exact: (item.path === '/')}\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- action -->\n <ion-item *ngIf=\"!loading && item.action\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n (click)=\"doAction(item.action, $event)\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- divider -->\n <ion-item-divider @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}}\"\n *ngIf=\"!loading && !item.path && !item.action\">\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item-divider>\n\n </ion-menu-toggle>\n </ion-list>\n </ion-content>\n\n <ion-footer class=\"hidden-xs hidden-sm\">\n <ion-toolbar>\n\n <ion-buttons slot=\"start\">\n <ion-button mat-icon-button color=\"accent\" (click)=\"openAboutModal($event)\">\n <mat-icon slot=\"icon-only\">help_outline</mat-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title (click)=\"openAboutModal($event)\" color=\"medium\">\n {{'MENU.FOOTER_VERSION_ABOUT'| translate: {version: appVersion} }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <button mat-icon-button color=\"accent\" (click)=\"toggleSplitPaneShow($event)\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(splitPane.when ? 'COMMON.BTN_HIDE_MENU' : 'COMMON.BTN_SHOW_MENU') |translate\">\n <mat-icon><span>{{splitPane.when ? '&#xab;' : '&#xbb;'}}</span></mat-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n\n </ion-menu>\n\n <ng-content></ng-content>\n\n</ion-split-pane>\n",
21434
+ template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n<!-- todo ajouter ici les 2 composants du module social ??? -->\n\n </ion-row>\n </ion-grid>\n\n </ion-toolbar>\n\n <!-- User not logged -->\n <ng-template #notLogin>\n <mat-toolbar class=\"ion-padding\" @fadeInAnimation\n style=\"height: unset; display: block; margin: auto; text-align: center;\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"150px;\">\n <span *ngIf=\"!logo\" style=\"width: 150px\">{{appName}}</span>\n </mat-toolbar>\n </ng-template>\n </ion-header>\n\n <ion-content [class.has-user-header]=\"isLogin\">\n\n <ion-list lines=\"none\">\n <ion-menu-toggle auto-hide=\"false\"\n [class.flex-spacer]=\"item.cssClass == 'flex-spacer'\"\n *ngFor=\"let item of $items | async\">\n\n <!-- link -->\n <ion-item *ngIf=\"!loading && item.path\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n routerLinkActive=\"selected\"\n [routerLinkActiveOptions]=\"{exact: (item.path === '/')}\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- action -->\n <ion-item *ngIf=\"!loading && item.action\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n (click)=\"doAction(item.action, $event)\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- divider -->\n <ion-item-divider @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}}\"\n *ngIf=\"!loading && !item.path && !item.action\">\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item-divider>\n\n </ion-menu-toggle>\n </ion-list>\n </ion-content>\n\n <ion-footer class=\"hidden-xs hidden-sm\">\n <ion-toolbar>\n\n <ion-buttons slot=\"start\">\n <ion-button mat-icon-button color=\"accent\" (click)=\"openAboutModal($event)\">\n <mat-icon slot=\"icon-only\">help_outline</mat-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title (click)=\"openAboutModal($event)\" color=\"medium\">\n {{'MENU.FOOTER_VERSION_ABOUT'| translate: {version: appVersion} }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <button mat-icon-button color=\"accent\" (click)=\"toggleSplitPaneShow($event)\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(splitPane.when ? 'COMMON.BTN_HIDE_MENU' : 'COMMON.BTN_SHOW_MENU') |translate\">\n <mat-icon><span>{{splitPane.when ? '&#xab;' : '&#xbb;'}}</span></mat-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n\n </ion-menu>\n\n <ng-content></ng-content>\n\n</ion-split-pane>\n",
21442
21435
  animations: [fadeInAnimation],
21443
21436
  changeDetection: ChangeDetectionStrategy.OnPush,
21444
21437
  styles: ["ion-menu{--ion-item-background:transparent;--ion-item-divider-background:transparent;--ion-item-icon-color:var(--ion-color-primary-tint);--ion-item-text-color:var(--ion-color-primary-tint);--ion-item-background-selected:var(--ion-color-secondary100);--ion-item-text-color-selected:var(--ion-color-primary);--ion-item-icon-color-selected:var(--ion-color-primary);--ion-item-text-color-disable:var(--ion-color-medium);--ion-item-icon-color-disable:var(--ion-color-medium)}ion-menu ion-header ion-text{color:var(--ion-color-primary)}ion-menu ion-header .user-avatar{background-size:cover;background-repeat:no-repeat;background-position:50%;background-color:var(--ion-color-secondary);border:1px solid var(--ion-color-primary);overflow:hidden!important;font-size:var(--avatar-size,60px)!important;line-height:var(--avatar-size,60px);height:var(--avatar-size,60px)!important;width:var(--avatar-size,60px)!important;border-radius:50%;display:inline-block}ion-menu ion-header .user-logo{text-align:right}ion-menu ion-header .user-logo img{max-width:120px;max-height:var(--avatar-size,60px);width:auto}ion-menu ion-header .username{padding-top:0;margin-top:0;margin-bottom:0;width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}ion-menu ion-header button[mat-button]{padding:0;text-align:start!important;width:100%}ion-menu .scroll-content{margin-top:79px!important}ion-menu .has-user-header .scroll-content{margin-top:188px!important}ion-menu ion-content.has-profile-header{--offset-top:188px}ion-menu ion-content.no-profile-header{--offset-top:79px}ion-menu ion-content ion-list{min-height:100%;display:flex;flex-direction:column;justify-content:flex-start}ion-menu ion-content ion-list ion-menu-toggle.flex-spacer{flex:1 1 auto;display:flex;flex-direction:column;justify-content:flex-end}ion-menu ion-content ion-list ion-item.primary{--ion-item-icon-color:var(--ion-color-primary-tint);--ion-item-text-color:var(--ion-color-primary-tint)}ion-menu ion-content ion-list ion-item.secondary{--ion-item-icon-color:var(--ion-color-secondary-tint);--ion-item-text-color:var(--ion-color-secondary-tint)}ion-menu ion-content ion-list ion-item.tertiary{--ion-item-icon-color:var(--ion-color-tertiary-tint);--ion-item-text-color:var(--ion-color-tertiary-tint)}ion-menu ion-content ion-list ion-item.danger{--ion-item-icon-color:var(--ion-color-danger-tint);--ion-item-text-color:var(--ion-color-danger-tint)}ion-menu ion-content ion-list ion-item.medium{--ion-item-icon-color:var(--ion-color-medium-shade);--ion-item-text-color:var(--ion-color-medium-shade)}ion-menu ion-content ion-list ion-item.dark{--ion-item-icon-color:var(--ion-color-dark-tint);--ion-item-text-color:var(--ion-color-dark-tint)}ion-menu ion-content ion-list ion-item ion-icon,ion-menu ion-content ion-list ion-item mat-icon{color:var(--ion-item-icon-color)!important;fill:currentColor;stroke:currentColor}ion-menu ion-content ion-list ion-item ion-label,ion-menu ion-content ion-list ion-item ion-text{color:var(--ion-item-text-color)!important}ion-menu ion-content ion-list ion-item.selected{background-color:var(--ion-item-background-selected)!important;--color-hover:var(--ion-item-background-selected)!important}ion-menu ion-content ion-list ion-item.selected ion-icon,ion-menu ion-content ion-list ion-item.selected mat-icon{color:var(--ion-item-icon-color-selected)!important;fill:currentColor;stroke:currentColor}ion-menu ion-content ion-list ion-item.selected ion-label,ion-menu ion-content ion-list ion-item.selected ion-text{color:var(--ion-item-text-color-selected)!important}ion-menu ion-content ion-list ion-item.selected:hover{--color-hover:var(--ion-item-background-selected)!important;--ion-item-icon-color-selected:var(--ion-item-icon-color)!important;--ion-item-text-color-selected:var(--ion-item-text-color)!important}ion-menu ion-footer{display:block!important}ion-menu ion-footer ion-toolbar ion-title{cursor:pointer;font-size:12pt;font-weight:400;text-align:center;padding:0 8px}ion-menu ion-footer ion-toolbar ion-button{--width:40px}@media screen and (max-width:767px){ion-menu ion-footer{display:none!important;visibility:hidden!important}}@media screen and (min-width:768px){ion-menu ion-scroll{overflow-y:auto!important}ion-menu .user-avatar{font-size:var(--avatar-size,80px)!important;line-height:var(--avatar-size,80px);height:var(--avatar-size,80px)!important;width:var(--avatar-size,80px)!important}ion-menu .user-logo img{max-height:var(--avatar-size,80px)}}"]
@@ -25959,34 +25952,47 @@ const UserEventFragments = {
25959
25952
  const moment$6 = momentImported;
25960
25953
  const UserEventServiceToken = new InjectionToken('UserEventService');
25961
25954
  class AbstractUserEventService extends BaseGraphqlService {
25962
- constructor(graphql, accountService, network, translate, toastController, queries, mutations, subscriptions, environment) {
25955
+ constructor(graphql, accountService, network, translate, queries, mutations, subscriptions, environment) {
25963
25956
  super(graphql, environment);
25964
25957
  this.graphql = graphql;
25965
25958
  this.accountService = accountService;
25966
25959
  this.network = network;
25967
25960
  this.translate = translate;
25968
- this.toastController = toastController;
25969
25961
  this.queries = queries;
25970
25962
  this.mutations = mutations;
25971
25963
  this.subscriptions = subscriptions;
25972
25964
  this.environment = environment;
25973
- this._count$ = new BehaviorSubject(0);
25974
- this._subscriptions = new Subscription();
25965
+ this.count$ = new BehaviorSubject(0);
25975
25966
  this.listeners = [];
25967
+ this._subscriptions = new Subscription();
25976
25968
  this._logPrefix = '[user-event-service] ';
25977
25969
  // For DEV only
25978
25970
  this._debug = !(environment === null || environment === void 0 ? void 0 : environment.production);
25979
- // listen login/logout
25980
- this._subscriptions.add(accountService.onLogin.subscribe(() => __awaiter(this, void 0, void 0, function* () {
25981
- const count = yield this.count(this.defaultFilter());
25982
- if (count && this._debug) {
25983
- console.debug(`${this._logPrefix}Received ${count} unread notifications`);
25984
- }
25985
- this._count$.next(count);
25986
- })));
25987
25971
  }
25988
25972
  get userEventCount() {
25989
- return this._count$.asObservable();
25973
+ return this.count$.asObservable();
25974
+ }
25975
+ ngOnStart() {
25976
+ return __awaiter(this, void 0, void 0, function* () {
25977
+ // Update component when refresh is need (=login events)
25978
+ this._subscriptions.add(merge(this.accountService.onLogin, this.accountService.onLogout)
25979
+ .pipe(
25980
+ // Wait account service ready (can be restarted)
25981
+ mergeMap(() => this.accountService.ready()), map(() => this.accountService.isLogin()), distinctUntilChanged())
25982
+ .subscribe(login => {
25983
+ if (login) {
25984
+ this.onLogin();
25985
+ }
25986
+ else {
25987
+ this.onLogout();
25988
+ }
25989
+ }));
25990
+ // First attempt if account is ready
25991
+ yield this.accountService.ready();
25992
+ if (this.accountService.isLogin()) {
25993
+ setTimeout(() => this.onLogin());
25994
+ }
25995
+ });
25990
25996
  }
25991
25997
  ngOnDestroy() {
25992
25998
  this._subscriptions.unsubscribe();
@@ -25997,13 +26003,15 @@ class AbstractUserEventService extends BaseGraphqlService {
25997
26003
  watchPage(page, filter, options) {
25998
26004
  var _a;
25999
26005
  let now = this._debug && Date.now();
26000
- //if (this._debug)
26006
+ if (!filter) {
26007
+ filter = this.defaultFilter();
26008
+ }
26001
26009
  console.debug(`${this._logPrefix}Loading user events...`, filter);
26002
26010
  filter = this.asFilter(filter);
26003
26011
  // Force recipient to current issuer, if not admin and not specified
26004
- if (isEmptyArray(filter.recipients) || !this.accountService.isAdmin()) {
26012
+ if (isEmptyArray(filter === null || filter === void 0 ? void 0 : filter.recipients) || !this.accountService.isAdmin()) {
26005
26013
  const recipient = this.defaultRecipient();
26006
- if (!((_a = filter.recipients) === null || _a === void 0 ? void 0 : _a.includes(recipient))) {
26014
+ if (!((_a = filter === null || filter === void 0 ? void 0 : filter.recipients) === null || _a === void 0 ? void 0 : _a.includes(recipient))) {
26007
26015
  console.warn('[user-events-service] Force user event filter.recipient=' + recipient);
26008
26016
  filter.recipients = [recipient];
26009
26017
  }
@@ -26013,23 +26021,26 @@ class AbstractUserEventService extends BaseGraphqlService {
26013
26021
  queryName: withContent ? 'LoadAllWithContent' : 'LoadAll',
26014
26022
  query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26015
26023
  variables: {
26016
- page: Object.assign({ sortBy: 'updateDate', sortDirection: 'desc' }, page),
26024
+ page: Object.assign(Object.assign({ sortBy: 'creationDate' }, page), {
26025
+ // @ts-ignore
26026
+ sortDirection: (page.sortDirection || 'desc').toUpperCase() }),
26017
26027
  filter: filter && filter.asPodObject()
26018
26028
  },
26019
26029
  arrayFieldName: 'data',
26020
26030
  error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
26021
- fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || "cache-first"
26031
+ fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || 'cache-first'
26022
26032
  })
26023
26033
  .pipe(map(res => {
26024
- const data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(this.processUserEvent);
26034
+ let data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(value => this.processUserEvent(value, this));
26025
26035
  if (now) {
26026
26036
  console.debug(`${this._logPrefix}${data.length} user events loaded in ${Date.now() - now}ms`);
26027
26037
  now = null;
26028
26038
  }
26029
- const unreadCount = this.unreadEvents(data);
26039
+ // Must re-order because of listenChanges result will add new event at the end
26040
+ data = EntityUtils.sort(data, page.sortBy, page.sortDirection);
26030
26041
  return {
26031
26042
  data,
26032
- total: toNumber(res === null || res === void 0 ? void 0 : res.total, unreadCount)
26043
+ total: toNumber(res === null || res === void 0 ? void 0 : res.total, data.length)
26033
26044
  };
26034
26045
  }));
26035
26046
  }
@@ -26043,7 +26054,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26043
26054
  data: entity
26044
26055
  });
26045
26056
  // Update count
26046
- this._count$.next(this._count$.value + 1);
26057
+ this.count$.next(this.count$.value + 1);
26047
26058
  }
26048
26059
  count(filter, options) {
26049
26060
  var _a;
@@ -26053,7 +26064,9 @@ class AbstractUserEventService extends BaseGraphqlService {
26053
26064
  return undefined;
26054
26065
  }
26055
26066
  if (!filter)
26056
- throw new Error(`Missing argument 'filter'`);
26067
+ filter = this.defaultFilter();
26068
+ // Apply last reset date as start date
26069
+ filter.startDate = this.resetCountDate;
26057
26070
  filter = this.asFilter(filter);
26058
26071
  if (this._debug)
26059
26072
  console.debug(`${this._logPrefix}Counting user events with filter:`, filter);
@@ -26068,6 +26081,34 @@ class AbstractUserEventService extends BaseGraphqlService {
26068
26081
  return res.total;
26069
26082
  });
26070
26083
  }
26084
+ listenCountChanges(filter, options) {
26085
+ if (!this.subscriptions.listenCountChanges) {
26086
+ console.warn(`${this._logPrefix}Subscription query 'listenCountChanges' not provided, skip.`);
26087
+ return of();
26088
+ }
26089
+ if (!filter)
26090
+ filter = this.defaultFilter();
26091
+ // Apply last reset date as start date
26092
+ filter.startDate = this.resetCountDate;
26093
+ filter = this.asFilter(filter);
26094
+ if (this._debug)
26095
+ console.debug(`${this._logPrefix}[WS] Listening count changes for user events with filter:`, filter);
26096
+ return this.graphql.subscribe({
26097
+ query: this.subscriptions.listenCountChanges,
26098
+ fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
26099
+ variables: { filter: filter.asPodObject(), interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
26100
+ error: {
26101
+ code: SocialErrorCodes.SUBSCRIBE_USER_EVENTS_ERROR,
26102
+ message: 'SOCIAL.ERROR.SUBSCRIBE_USER_EVENTS_ERROR'
26103
+ }
26104
+ }).pipe(map(({ total }) => {
26105
+ if (total && this._debug)
26106
+ console.debug(`${this._logPrefix}Received new user events count:`, total);
26107
+ // update count
26108
+ this.count$.next(total);
26109
+ return total;
26110
+ }));
26111
+ }
26071
26112
  listenChanges(filter, options) {
26072
26113
  var _a;
26073
26114
  if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenChanges)) {
@@ -26075,7 +26116,7 @@ class AbstractUserEventService extends BaseGraphqlService {
26075
26116
  return of();
26076
26117
  }
26077
26118
  if (!filter)
26078
- throw new Error(`Missing argument 'filter'`);
26119
+ filter = this.defaultFilter();
26079
26120
  filter = this.asFilter(filter);
26080
26121
  const withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
26081
26122
  if (this._debug)
@@ -26091,14 +26132,12 @@ class AbstractUserEventService extends BaseGraphqlService {
26091
26132
  }).pipe(map(({ data }) => {
26092
26133
  if (data && this._debug)
26093
26134
  console.debug(`${this._logPrefix}Received new user events:`, data);
26094
- const updatedData = data === null || data === void 0 ? void 0 : data.map(this.processUserEvent);
26135
+ const updatedData = data === null || data === void 0 ? void 0 : data.map(value => this.processUserEvent(value, this));
26095
26136
  // Update cache
26096
26137
  this.insertIntoMutableCachedQueries(this.graphql.cache, {
26097
26138
  query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
26098
26139
  data: updatedData
26099
26140
  });
26100
- // update count
26101
- this._count$.next(this.unreadEvents(updatedData));
26102
26141
  return updatedData;
26103
26142
  }));
26104
26143
  }
@@ -26141,9 +26180,15 @@ class AbstractUserEventService extends BaseGraphqlService {
26141
26180
  }
26142
26181
  save(entity, options) {
26143
26182
  return __awaiter(this, void 0, void 0, function* () {
26183
+ if (!this.mutations.save) {
26184
+ if (!this.mutations.saveAll)
26185
+ throw new Error('Not implemented');
26186
+ const allData = yield this.saveAll([entity], options);
26187
+ return allData === null || allData === void 0 ? void 0 : allData[0];
26188
+ }
26144
26189
  this.fillDefaultProperties(entity);
26145
26190
  // Transform into json
26146
- const isNew = isNil(entity.id);
26191
+ const withContent = !!entity.content;
26147
26192
  const json = entity.asObject();
26148
26193
  const now = Date.now();
26149
26194
  if (this._debug)
@@ -26162,39 +26207,87 @@ class AbstractUserEventService extends BaseGraphqlService {
26162
26207
  console.debug(`${this._logPrefix}User event saved in ${Date.now() - now}ms`, entity);
26163
26208
  this.copyIdAndUpdateDate(savedEntity, entity);
26164
26209
  // Add to cache
26165
- if (isNew) {
26166
- this.insertIntoMutableCachedQueries(proxy, {
26167
- query: this.queries.loadAll,
26168
- data: Object.assign(Object.assign({}, savedEntity), { content: null })
26169
- });
26210
+ if (withContent) {
26170
26211
  this.insertIntoMutableCachedQueries(proxy, {
26171
26212
  query: this.queries.loadAllWithContent,
26172
26213
  data: savedEntity
26173
26214
  });
26174
26215
  }
26216
+ else {
26217
+ this.insertIntoMutableCachedQueries(proxy, {
26218
+ query: this.queries.loadAll,
26219
+ data: Object.assign(Object.assign({}, savedEntity), { content: null })
26220
+ });
26221
+ }
26175
26222
  }
26176
26223
  }
26177
26224
  });
26178
26225
  return entity;
26179
26226
  });
26180
26227
  }
26181
- saveAll(data, opts) {
26182
- return Promise.all(data
26183
- .map(entity => this.save(entity, opts)));
26228
+ saveAll(entities, opts) {
26229
+ return __awaiter(this, void 0, void 0, function* () {
26230
+ if (isEmptyArray(entities))
26231
+ return entities;
26232
+ if (!this.mutations.saveAll) {
26233
+ if (!this.mutations.save)
26234
+ throw new Error('Not implemented');
26235
+ // Save one by one
26236
+ return chainPromises(entities.map((entity) => () => this.save(entity, opts)));
26237
+ }
26238
+ // Transform into json
26239
+ const json = entities.map(entity => {
26240
+ this.fillDefaultProperties(entity);
26241
+ return entity.asObject();
26242
+ });
26243
+ const now = Date.now();
26244
+ if (this._debug)
26245
+ console.debug(`${this._logPrefix}Saving user events...`, json);
26246
+ yield this.graphql.mutate({
26247
+ mutation: this.mutations.saveAll,
26248
+ variables: {
26249
+ data: json
26250
+ },
26251
+ error: { code: SocialErrorCodes.SAVE_USER_EVENT_ERROR, message: 'SOCIAL.ERROR.SAVE_USER_EVENT_ERROR' },
26252
+ update: (proxy, { data }) => {
26253
+ // Update entity
26254
+ const savedEntities = (data === null || data === void 0 ? void 0 : data.data) || [];
26255
+ if (savedEntities.length) {
26256
+ if (this._debug)
26257
+ console.debug(`${this._logPrefix}User events saved in ${Date.now() - now}ms`, savedEntities);
26258
+ entities.forEach(entity => {
26259
+ const savedEntity = savedEntities.find((e) => EntityUtils.equals(e, entity, 'id'));
26260
+ this.copyIdAndUpdateDate(savedEntity, entity);
26261
+ });
26262
+ // Add to cache (assuming all with content)
26263
+ this.insertIntoMutableCachedQueries(proxy, {
26264
+ query: this.queries.loadAllWithContent,
26265
+ data: savedEntities
26266
+ });
26267
+ }
26268
+ }
26269
+ });
26270
+ return entities;
26271
+ });
26184
26272
  }
26185
- markAsRead(entity) {
26273
+ markAsRead(entities) {
26186
26274
  return __awaiter(this, void 0, void 0, function* () {
26187
- // Get onRead listeners
26188
- const onReadListeners = (this.listeners || []).filter(listener => !!listener.onRead).filter(listener => listener.accept(entity));
26189
- if (onReadListeners.length) {
26190
- for (const listener of onReadListeners) {
26191
- yield listener.onRead(entity);
26275
+ const userEventWithoutReadListeners = [];
26276
+ for (const entity of (entities || [])) {
26277
+ // Get onRead listeners
26278
+ const onReadListeners = (this.listeners || []).filter(listener => !!listener.onRead).filter(listener => listener.accept(entity));
26279
+ if (onReadListeners.length) {
26280
+ for (const listener of onReadListeners) {
26281
+ yield listener.onRead(entity);
26282
+ }
26283
+ }
26284
+ else {
26285
+ // Add to this list for default operation
26286
+ userEventWithoutReadListeners.push(entity);
26192
26287
  }
26193
26288
  }
26194
- else {
26195
- // Use default
26196
- yield this.defaultMarkAsRead(entity);
26197
- }
26289
+ // Use default
26290
+ yield this.defaultMarkAsRead(userEventWithoutReadListeners);
26198
26291
  });
26199
26292
  }
26200
26293
  registerListener(listener) {
@@ -26202,37 +26295,75 @@ class AbstractUserEventService extends BaseGraphqlService {
26202
26295
  this.listeners = [];
26203
26296
  this.listeners.push(listener);
26204
26297
  }
26298
+ resetCount() {
26299
+ this.count$.next(undefined);
26300
+ this.resetCountDate = moment$6();
26301
+ // restart listening count changes
26302
+ this.startListenCountChanges();
26303
+ }
26205
26304
  /* -- protected methods -- */
26206
- processUserEvent(source) {
26305
+ onLogin() {
26306
+ return __awaiter(this, void 0, void 0, function* () {
26307
+ // Get first count
26308
+ const count = yield this.count(undefined);
26309
+ if (this._debug)
26310
+ console.debug(`${this._logPrefix}Receiving user events count`, count);
26311
+ // Update count
26312
+ this.count$.next(count);
26313
+ // Then listen changes
26314
+ this.startListenCountChanges();
26315
+ });
26316
+ }
26317
+ onLogout() {
26318
+ this.stopListenCountChanges();
26319
+ }
26320
+ startListenCountChanges() {
26321
+ this.stopListenCountChanges();
26322
+ this._listenSubscription = this.listenCountChanges(undefined).subscribe();
26323
+ }
26324
+ stopListenCountChanges() {
26325
+ var _a;
26326
+ (_a = this._listenSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
26327
+ this._listenSubscription = undefined;
26328
+ }
26329
+ processUserEvent(source, that) {
26330
+ that = that || this;
26207
26331
  // Convert json source to IUserEvent
26208
- let target = this.fromObject(source);
26332
+ let target = that.fromObject(source);
26209
26333
  // Get listeners
26210
- const listeners = (this.listeners || []).filter(listener => listener.onReceived).filter(listener => listener.accept(target));
26334
+ const listeners = (that.listeners || []).filter(listener => listener.onReceived).filter(listener => listener.accept(target));
26211
26335
  for (const listener of listeners) {
26212
26336
  if (target) {
26213
26337
  target = listener.onReceived(target);
26214
26338
  }
26215
26339
  else {
26216
- if (this._debug)
26217
- console.debug(`${this._logPrefix}Event has been rejected by a listener`, source);
26340
+ if (that._debug)
26341
+ console.debug(`${that._logPrefix}Event has been rejected by a listener`, source);
26218
26342
  break;
26219
26343
  }
26220
26344
  }
26221
26345
  return target;
26222
26346
  }
26223
- defaultMarkAsRead(userEvent) {
26347
+ defaultMarkAsRead(userEvents) {
26224
26348
  return __awaiter(this, void 0, void 0, function* () {
26225
- if (!userEvent)
26349
+ if (!userEvents)
26226
26350
  throw new Error(`${this._logPrefix}Invalid event to save`);
26351
+ if (!userEvents.length)
26352
+ return;
26227
26353
  // set read date
26228
- userEvent.readDate = moment$6();
26229
- if (!userEvent.id || userEvent.id < 0) {
26354
+ userEvents.forEach(userEvent => userEvent.readDate = moment$6());
26355
+ // split local/remote entities
26356
+ const localEntities = userEvents.filter(userEvent => !userEvent.id || userEvent.id < 0);
26357
+ const remoteEntities = userEvents.filter(userEvent => userEvent.id > 0);
26358
+ // save local entities
26359
+ if (localEntities.length) {
26230
26360
  if (this._debug)
26231
26361
  console.debug(`${this._logPrefix}Save local user event`);
26232
26362
  // TODO !!!!!!!!!!!!!
26233
26363
  }
26234
- else {
26235
- yield this.save(userEvent);
26364
+ // save remote entities
26365
+ if (remoteEntities.length) {
26366
+ yield this.saveAll(remoteEntities);
26236
26367
  }
26237
26368
  });
26238
26369
  }
@@ -26269,7 +26400,6 @@ AbstractUserEventService.ctorParameters = () => [
26269
26400
  { type: AccountService },
26270
26401
  { type: NetworkService },
26271
26402
  { type: TranslateService },
26272
- { type: ToastController },
26273
26403
  { type: undefined },
26274
26404
  { type: undefined },
26275
26405
  { type: undefined },
@@ -26310,7 +26440,7 @@ const userEventMutations = {
26310
26440
  };
26311
26441
  class UserEventService extends AbstractUserEventService {
26312
26442
  constructor(graphql, accountService, network, translate, toastController, environment) {
26313
- super(graphql, accountService, network, translate, toastController, userEventQueries, userEventMutations, undefined, environment);
26443
+ super(graphql, accountService, network, translate, userEventQueries, userEventMutations, undefined, environment);
26314
26444
  this.graphql = graphql;
26315
26445
  this.accountService = accountService;
26316
26446
  this.network = network;
@@ -26581,17 +26711,47 @@ UserEventsTable.propDecorators = {
26581
26711
  };
26582
26712
 
26583
26713
  class UserEventNotificationList {
26584
- constructor(popoverController) {
26714
+ constructor(cd, popoverController, userEventService) {
26715
+ this.cd = cd;
26585
26716
  this.popoverController = popoverController;
26717
+ this.userEventService = userEventService;
26718
+ this.debug = false;
26719
+ this.userEvents = new BehaviorSubject(undefined);
26720
+ this.subscriptions = new Subscription();
26586
26721
  }
26587
26722
  ngOnInit() {
26723
+ // Watch all user events
26724
+ this.subscriptions.add(this.userEventService
26725
+ .watchAll(0, 10, 'creationDate', "desc", undefined)
26726
+ .subscribe(result => {
26727
+ if (this.debug)
26728
+ console.debug(`[user-event-notification-list] receiving ${result.total} user events`, result.data);
26729
+ this.userEvents.next(result.data);
26730
+ this.markForCheck();
26731
+ }));
26732
+ // Listen changes
26733
+ this.subscriptions.add(this.userEventService.listenChanges(undefined)
26734
+ .subscribe(data => {
26735
+ if (this.debug)
26736
+ console.debug(`[user-event-notification-list] receiving ${data.length} new user events`, data);
26737
+ }));
26738
+ }
26739
+ ngOnDestroy() {
26740
+ this.subscriptions.unsubscribe();
26588
26741
  }
26589
- read($event, userEvent) {
26742
+ read(event, userEvent) {
26590
26743
  var _a;
26591
26744
  if (userEvent === null || userEvent === void 0 ? void 0 : userEvent.readDate)
26592
26745
  return;
26593
26746
  (_a = this.readEvent) === null || _a === void 0 ? void 0 : _a.emit(userEvent);
26594
26747
  }
26748
+ readAll(event) {
26749
+ var _a;
26750
+ const unreadUserEvents = (this.userEvents.value || []).filter(value => !value.readDate);
26751
+ if (!unreadUserEvents.length)
26752
+ return;
26753
+ (_a = this.readEvents) === null || _a === void 0 ? void 0 : _a.emit(unreadUserEvents);
26754
+ }
26595
26755
  executeAction(action, userEvent) {
26596
26756
  // Execute then close popover
26597
26757
  action.executeAction(userEvent);
@@ -26600,69 +26760,74 @@ class UserEventNotificationList {
26600
26760
  dismiss() {
26601
26761
  this.popoverController.dismiss();
26602
26762
  }
26763
+ markForCheck() {
26764
+ this.cd.markForCheck();
26765
+ }
26603
26766
  }
26604
26767
  UserEventNotificationList.decorators = [
26605
26768
  { type: Component, args: [{
26606
26769
  selector: 'app-user-event-notification-list',
26607
- template: "\n<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!(userEvents | async)?.length\">\n {{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}\n </ion-item>\n <ion-item\n *ngFor=\"let userEvent of userEvents | async\"\n (click)=\"read($event, userEvent)\"\n >\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"userEvent.avatar; else avatarIcon\" src=\"{{ userEvent.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"userEvent.avatarIcon\"\n [ref]=\"userEvent.avatarIcon\"\n height=\"40\"\n width=\"40\"\n ></app-icon>\n </ng-template>\n\n </ion-avatar>\n\n <ion-grid class=\"ion-no-margin ion-no-padding\">\n <ion-row>\n <ion-col>\n <p [class.unread]=\"!userEvent.readDate\">\n {{userEvent.message}}\n </p>\n </ion-col>\n </ion-row>\n <ion-row *ngIf=\"userEvent.actions?.length\">\n <ion-col>\n <p>\n <span *ngFor=\"let action of userEvent.actions\">\n <a\n [style.margin-right.px]=\"8\"\n [style.cursor]=\"'pointer'\"\n (click)=\"executeAction(action, userEvent)\"\n >\n {{ '&#10142;&nbsp;' + action.name}}\n </a>\n </span>\n </p>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <app-icon\n *ngIf=\"userEvent.icon\"\n [ref]=\"userEvent.icon\"\n height=\"16\"\n width=\"16\"\n [style.vertical-align]=\"'sub'\"\n ></app-icon>\n <small>\n <span>{{userEvent.creationDate|dateFromNow}}</span>\n <span [style.color]=\"'gray'\">{{ ' | ' + (userEvent.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
26770
+ template: "\n<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!(userEvents | async)?.length\">\n {{'SOCIAL.USER_EVENT.NOTIFICATION.EMPTY' | translate}}\n </ion-item>\n <ion-item\n *ngFor=\"let userEvent of userEvents | async\"\n (click)=\"read($event, userEvent)\"\n >\n\n <ion-avatar slot=\"start\">\n\n <img *ngIf=\"userEvent.avatar; else avatarIcon\" src=\"{{ userEvent.avatar }}\">\n\n <ng-template #avatarIcon>\n <app-icon\n *ngIf=\"userEvent.avatarIcon\"\n [ref]=\"userEvent.avatarIcon\"\n height=\"40\"\n width=\"40\"\n ></app-icon>\n </ng-template>\n\n </ion-avatar>\n\n <ion-grid class=\"ion-no-margin ion-no-padding\">\n <ion-row>\n <ion-col>\n <p [class.unread]=\"!userEvent.readDate\">\n {{userEvent.message}}\n </p>\n </ion-col>\n </ion-row>\n <ion-row *ngIf=\"userEvent.actions?.length\">\n <ion-col>\n <p>\n <span *ngFor=\"let action of userEvent.actions\">\n <a\n [style.margin-right.px]=\"8\"\n [style.cursor]=\"'pointer'\"\n (click)=\"executeAction(action, userEvent)\"\n >\n {{ '&#10142;&nbsp;' + action.name}}\n </a>\n </span>\n </p>\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <app-icon\n *ngIf=\"userEvent.icon\"\n [ref]=\"userEvent.icon\"\n height=\"16\"\n width=\"16\"\n [style.vertical-align]=\"'sub'\"\n ></app-icon>\n <small>\n <span>{{userEvent.creationDate|dateFromNow}}</span>\n <span [style.color]=\"'gray'\">{{ ' | ' + (userEvent.creationDate|dateFormat:{time:true}) }}</span>\n </small>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n <ion-row class=\"ion-list-footer column\">\n <ion-col>\n <a style=\"cursor: pointer\" (click)=\"readAll($event)\">{{'SOCIAL.USER_EVENT.NOTIFICATION.READ_ALL' | translate}}</a>\n </ion-col>\n </ion-row>\n\n</ion-list>\n",
26771
+ changeDetection: ChangeDetectionStrategy.OnPush,
26608
26772
  styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}.unread{font-weight:700}"]
26609
26773
  },] }
26610
26774
  ];
26611
26775
  UserEventNotificationList.ctorParameters = () => [
26612
- { type: PopoverController }
26776
+ { type: ChangeDetectorRef },
26777
+ { type: PopoverController },
26778
+ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [UserEventServiceToken,] }] }
26613
26779
  ];
26614
26780
  UserEventNotificationList.propDecorators = {
26781
+ debug: [{ type: Input }],
26615
26782
  titleI18n: [{ type: Input }],
26616
- userEvents: [{ type: Input }],
26617
- readEvent: [{ type: Output }]
26783
+ readEvent: [{ type: Output }],
26784
+ readEvents: [{ type: Output }]
26618
26785
  };
26619
26786
 
26620
26787
  class UserEventNotificationComponent {
26621
- constructor(userEventService, accountService, popoverController, cd) {
26788
+ constructor(userEventService, accountService, popoverController) {
26622
26789
  this.userEventService = userEventService;
26623
26790
  this.accountService = accountService;
26624
26791
  this.popoverController = popoverController;
26625
- this.cd = cd;
26626
26792
  this.debug = false;
26627
26793
  this.titleI18n = 'SOCIAL.USER_EVENT.NOTIFICATION.TITLE';
26628
26794
  this.disabled = false;
26629
- this.userEventsSubject = new BehaviorSubject(undefined);
26630
- this._subscriptions = new Subscription();
26631
26795
  this._logPrefix = '[user-event-notification] ';
26632
26796
  this._readEvent = new EventEmitter();
26797
+ this._readEvents = new EventEmitter();
26633
26798
  }
26634
26799
  get count() {
26635
26800
  var _a;
26636
26801
  return (_a = this.userEventService) === null || _a === void 0 ? void 0 : _a.userEventCount.pipe(map(value => value === 0 ? undefined : value));
26637
26802
  }
26638
26803
  ngOnInit() {
26639
- var _a;
26640
- if (isNil(this.userEventService)) {
26641
- console.warn(`${this._logPrefix}No service injected`);
26642
- this.disabled = true;
26643
- return;
26644
- }
26645
- this._subscriptions.add(this.userEventService.watchAll(0, 10, 'creationDate', "desc", {
26646
- recipients: [(_a = this.accountService.person) === null || _a === void 0 ? void 0 : _a.pubkey]
26647
- }).subscribe(value => {
26648
- const data = value.data;
26649
- if (this.debug) {
26650
- console.debug(`${this._logPrefix}Receiving user events`, data);
26804
+ return __awaiter(this, void 0, void 0, function* () {
26805
+ if (isNil(this.userEventService)) {
26806
+ console.warn(`${this._logPrefix}No service injected`);
26807
+ this.disabled = true;
26808
+ return;
26651
26809
  }
26652
- this.userEventsSubject.next(data);
26653
- }));
26654
- this._readEvent.subscribe(value => {
26655
- this.userEventService.markAsRead(value);
26810
+ // Subscribe to read event
26811
+ this._readEvent.subscribe(value => {
26812
+ // default: mark event as read
26813
+ this.userEventService.markAsRead([value]);
26814
+ });
26815
+ this._readEvents.subscribe(value => {
26816
+ this.userEventService.markAsRead(value);
26817
+ });
26656
26818
  });
26657
26819
  }
26658
26820
  showList(event) {
26659
26821
  return __awaiter(this, void 0, void 0, function* () {
26822
+ // Reset count
26823
+ this.userEventService.resetCount();
26660
26824
  const popover = yield this.popoverController.create({
26661
26825
  component: UserEventNotificationList,
26662
26826
  componentProps: {
26827
+ debug: this.debug,
26663
26828
  titleI18n: this.titleI18n,
26664
- userEvents: this.userEventsSubject,
26665
- readEvent: this._readEvent
26829
+ readEvent: this._readEvent,
26830
+ readEvents: this._readEvents
26666
26831
  },
26667
26832
  backdropDismiss: true,
26668
26833
  keyboardClose: true,
@@ -26673,14 +26838,10 @@ class UserEventNotificationComponent {
26673
26838
  yield popover.present();
26674
26839
  });
26675
26840
  }
26676
- markForCheck() {
26677
- this.cd.markForCheck();
26678
- }
26679
26841
  ngOnDestroy() {
26680
26842
  if (this.debug) {
26681
26843
  console.debug(`${this._logPrefix}Destroying`);
26682
26844
  }
26683
- this._subscriptions.unsubscribe();
26684
26845
  }
26685
26846
  }
26686
26847
  UserEventNotificationComponent.decorators = [
@@ -26694,8 +26855,7 @@ UserEventNotificationComponent.decorators = [
26694
26855
  UserEventNotificationComponent.ctorParameters = () => [
26695
26856
  { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [UserEventServiceToken,] }] },
26696
26857
  { type: AccountService },
26697
- { type: PopoverController },
26698
- { type: ChangeDetectorRef }
26858
+ { type: PopoverController }
26699
26859
  ];
26700
26860
  UserEventNotificationComponent.propDecorators = {
26701
26861
  debug: [{ type: Input }],
@@ -26703,6 +26863,69 @@ UserEventNotificationComponent.propDecorators = {
26703
26863
  disabled: [{ type: Input }]
26704
26864
  };
26705
26865
 
26866
+ class UserEventTestService extends AbstractUserEventService {
26867
+ constructor(graphql, accountService, network, translate, environment) {
26868
+ super(graphql, accountService, network, translate, undefined, undefined, undefined, environment);
26869
+ this.graphql = graphql;
26870
+ this.accountService = accountService;
26871
+ this.network = network;
26872
+ this.translate = translate;
26873
+ this.environment = environment;
26874
+ this.userEvents = [];
26875
+ }
26876
+ fromObject(source) {
26877
+ return UserEvent.fromObject(source);
26878
+ }
26879
+ add(entity) {
26880
+ entity = this.processUserEvent(entity);
26881
+ entity.id = this.userEvents.length + 1;
26882
+ this.userEvents.push(entity);
26883
+ this.count$.next(this.userEvents.length);
26884
+ }
26885
+ asFilter(filter) {
26886
+ return filter;
26887
+ }
26888
+ count(filter, options) {
26889
+ return Promise.resolve(this.userEvents.length);
26890
+ }
26891
+ delete(entity) {
26892
+ return Promise.resolve(undefined);
26893
+ }
26894
+ deleteAll(data, opts) {
26895
+ return Promise.resolve(undefined);
26896
+ }
26897
+ listenChanges(filter, options) {
26898
+ return of();
26899
+ }
26900
+ save(entity, options) {
26901
+ var _a;
26902
+ 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));
26903
+ Object.assign(toSave, entity);
26904
+ return entity;
26905
+ }
26906
+ saveAll(data, opts) {
26907
+ return __awaiter(this, void 0, void 0, function* () {
26908
+ for (const entity of (data || [])) {
26909
+ yield this.save(entity);
26910
+ }
26911
+ return Promise.resolve(this.userEvents);
26912
+ });
26913
+ }
26914
+ watchAll(offset, size, sortBy, sortDirection, filter, options) {
26915
+ return of({ data: this.userEvents });
26916
+ }
26917
+ }
26918
+ UserEventTestService.decorators = [
26919
+ { type: Injectable }
26920
+ ];
26921
+ UserEventTestService.ctorParameters = () => [
26922
+ { type: GraphqlService },
26923
+ { type: AccountService },
26924
+ { type: NetworkService },
26925
+ { type: TranslateService },
26926
+ { type: Environment, decorators: [{ type: Optional }, { type: Inject, args: [ENVIRONMENT,] }] }
26927
+ ];
26928
+
26706
26929
  class UserEventModule {
26707
26930
  }
26708
26931
  UserEventModule.decorators = [
@@ -26720,6 +26943,9 @@ UserEventModule.decorators = [
26720
26943
  exports: [
26721
26944
  UserEventsTable,
26722
26945
  UserEventNotificationComponent
26946
+ ],
26947
+ providers: [
26948
+ { provide: UserEventServiceToken, useClass: UserEventTestService }
26723
26949
  ]
26724
26950
  },] }
26725
26951
  ];
@@ -26981,7 +27207,6 @@ const jobProgressionSubscription = gql `subscription UpdateJobProgression($id: I
26981
27207
  message
26982
27208
  current
26983
27209
  total
26984
- updateDate
26985
27210
  }
26986
27211
  }`;
26987
27212
  class JobProgressionService extends BaseGraphqlService {
@@ -29186,5 +29411,5 @@ CoreTestingModule.decorators = [
29186
29411
  * Generated bundle index. Do not edit.
29187
29412
  */
29188
29413
 
29189
- 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_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, 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, 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, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEvent, UserEventFilter, UserEventFragments, UserEventModule, UserEventNotificationComponent, UserEventService, UserEventServiceToken, UserEventTypes, UserEventsTable, 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, 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, AppIconComponent as ɵj, UserEventNotificationList as ɵk, JobProgressionList as ɵl, DateTestPage as ɵm, NumpadTestPage as ɵn, MatBadgeIconTestPage as ɵo, ToastTestingModule as ɵp, ToastTestingPage as ɵq };
29414
+ 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_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, 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, 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, UploadFile, UploadFileComponent, UploadFilePopover, UploadFileTestingModule, UploadFileTestingPage, UriUtils, UserEvent, UserEventFilter, UserEventFragments, UserEventModule, UserEventNotificationComponent, UserEventService, UserEventServiceToken, UserEventTypes, UserEventsTable, 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, 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, AppIconComponent as ɵj, UserEventNotificationList as ɵk, UserEventTestService as ɵl, JobProgressionList as ɵm, DateTestPage as ɵn, NumpadTestPage as ɵo, MatBadgeIconTestPage as ɵp, ToastTestingModule as ɵq, ToastTestingPage as ɵr };
29190
29415
  //# sourceMappingURL=sumaris-net.ngx-components.js.map