@sumaris-net/ngx-components 1.21.0-beta3 → 1.21.0-beta30

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 (33) hide show
  1. package/bundles/sumaris-net.ngx-components.umd.js +464 -160
  2. package/bundles/sumaris-net.ngx-components.umd.js.map +1 -1
  3. package/bundles/sumaris-net.ngx-components.umd.min.js +2 -2
  4. package/bundles/sumaris-net.ngx-components.umd.min.js.map +1 -1
  5. package/esm2015/src/app/core/menu/menu.component.js +2 -2
  6. package/esm2015/src/app/shared/pipes/date-diff-duration.pipe.js +8 -4
  7. package/esm2015/src/app/social/job/job.model.js +4 -2
  8. package/esm2015/src/app/social/job/job.service.js +2 -2
  9. package/esm2015/src/app/social/job/progression/job-progression.component.js +9 -5
  10. package/esm2015/src/app/social/job/progression/job-progression.list.js +3 -3
  11. package/esm2015/src/app/social/user-event/notification/user-event-notification.component.js +23 -31
  12. package/esm2015/src/app/social/user-event/notification/user-event-notification.list.js +48 -9
  13. package/esm2015/src/app/social/user-event/testing/user-event.testing.service.js +73 -0
  14. package/esm2015/src/app/social/user-event/user-event.model.js +1 -1
  15. package/esm2015/src/app/social/user-event/user-event.module.js +6 -1
  16. package/esm2015/src/app/social/user-event/user-event.service.js +174 -63
  17. package/esm2015/src/app/social/user-event/user-events.table.js +2 -2
  18. package/esm2015/sumaris-net.ngx-components.js +8 -7
  19. package/fesm2015/sumaris-net.ngx-components.js +324 -108
  20. package/fesm2015/sumaris-net.ngx-components.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/app/shared/pipes/date-diff-duration.pipe.d.ts +6 -2
  23. package/src/app/social/job/job.model.d.ts +2 -1
  24. package/src/app/social/user-event/notification/user-event-notification.component.d.ts +5 -8
  25. package/src/app/social/user-event/notification/user-event-notification.list.d.ts +18 -8
  26. package/src/app/social/user-event/testing/user-event.testing.service.d.ts +35 -0
  27. package/src/app/social/user-event/user-event.model.d.ts +1 -2
  28. package/src/app/social/user-event/user-event.service.d.ts +31 -11
  29. package/src/assets/i18n/en.json +2 -1
  30. package/src/assets/i18n/fr.json +2 -1
  31. package/src/theme/_ngx-components.scss +1 -0
  32. package/sumaris-net.ngx-components.d.ts +7 -6
  33. package/sumaris-net.ngx-components.metadata.json +1 -1
@@ -2328,17 +2328,21 @@
2328
2328
  return '';
2329
2329
  var startDate = this.dateAdapter.parse(value.startValue, DATE_ISO_PATTERN);
2330
2330
  var endDate = this.dateAdapter.parse(value.endValue, DATE_ISO_PATTERN);
2331
- return this.format(startDate, endDate);
2331
+ return this.format(startDate, endDate, args);
2332
2332
  };
2333
- DateDiffDurationPipe.prototype.format = function (startDate, endDate) {
2333
+ DateDiffDurationPipe.prototype.format = function (startDate, endDate, args) {
2334
2334
  var duration = moment.duration(endDate.diff(startDate));
2335
2335
  if (duration.asMinutes() < 0)
2336
2336
  return '';
2337
+ var withSeconds = args === null || args === void 0 ? void 0 : args.seconds;
2337
2338
  var timeDuration = moment(0)
2338
2339
  .hour(duration.hours())
2339
2340
  .minute(duration.minutes());
2341
+ if (withSeconds) {
2342
+ timeDuration.second(duration.seconds());
2343
+ }
2340
2344
  var days = Math.floor(duration.asDays());
2341
- return (days > 0 ? days.toString() + (this.dayUnit + ' ') : '') + timeDuration.format('HH:mm');
2345
+ return (days > 0 ? days.toString() + (this.dayUnit + ' ') : '') + timeDuration.format(withSeconds ? 'HH:mm:ss' : 'HH:mm');
2342
2346
  };
2343
2347
  return DateDiffDurationPipe;
2344
2348
  }());
@@ -24749,7 +24753,7 @@
24749
24753
  MenuComponent.decorators = [
24750
24754
  { type: i0.Component, args: [{
24751
24755
  selector: 'app-menu',
24752
- template: "<ion-split-pane #splitPane [contentId]=\"contentId\" (swiperight)=\"onSwipeRight($event)\">\n\n <ion-menu [id]=\"id\" [menuId]=\"menuId\" contentId=\"menu-content\">\n <ion-header>\n\n <ion-toolbar @fadeInAnimation *ngIf=\"isLogin; else notLogin\" class=\"ion-toolbar-top\">\n <ion-grid>\n <ion-row>\n <ion-col size=\"4\">\n <button type=\"button\" mat-flat-button\n class=\"user-avatar\" [class.primary]=\"!accountAvatar\"\n [style.background-image]=\"'url('+(accountAvatar||'./assets/img/person.png')+')'\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n </button>\n </ion-col>\n <ion-col size=\"8\" class=\"user-logo\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"108px;\"/>\n <span *ngIf=\"!logo\" width=\"108px;\">{{appName}}</span>\n </ion-col>\n </ion-row>\n <ion-row class=\"ion-no-padding\">\n\n <button mat-button type=\"button\"\n [routerLink]=\"['/account']\"\n routerDirection=\"root\"\n routerLinkActive=\"ion-color-primary\"\n (click)=\"close()\">\n <ion-label color=\"primary\" class=\"ion-text-wrap ion-text-start\">\n <h3 class=\"no-margin username\">\n <b>{{accountName}}</b>\n </h3>\n <h4>{{accountEmail}}</h4>\n </ion-label>\n </button>\n\n<!-- todo ajouter ici les 2 composants du module social -->\n\n </ion-row>\n </ion-grid>\n\n </ion-toolbar>\n\n <!-- User not logged -->\n <ng-template #notLogin>\n <mat-toolbar class=\"ion-padding\" @fadeInAnimation\n style=\"height: unset; display: block; margin: auto; text-align: center;\">\n <img *ngIf=\"logo\" src=\"{{logo}}\" [title]=\"'APP_NAME'|translate: {appName: appName}\" width=\"150px;\">\n <span *ngIf=\"!logo\" style=\"width: 150px\">{{appName}}</span>\n </mat-toolbar>\n </ng-template>\n </ion-header>\n\n <ion-content [class.has-user-header]=\"isLogin\">\n\n <ion-list lines=\"none\">\n <ion-menu-toggle auto-hide=\"false\"\n [class.flex-spacer]=\"item.cssClass == 'flex-spacer'\"\n *ngFor=\"let item of $items | async\">\n\n <!-- link -->\n <ion-item *ngIf=\"!loading && item.path\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n [routerLink]=\"item.path\"\n routerDirection=\"root\"\n routerLinkActive=\"selected\"\n [routerLinkActiveOptions]=\"{exact: (item.path === '/')}\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- action -->\n <ion-item *ngIf=\"!loading && item.action\"\n @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}} text-1x\"\n tappable\n (click)=\"doAction(item.action, $event)\">\n <ion-icon slot=\"start\" *ngIf=\"item.icon\" [name]=\"item.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"item.matIcon\">{{item.matIcon}}</mat-icon>\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item>\n\n <!-- divider -->\n <ion-item-divider @fadeInAnimation\n class=\"{{item.cssClass}} {{item.color}}\"\n *ngIf=\"!loading && !item.path && !item.action\">\n <ion-label translate>{{item.title}}</ion-label>\n </ion-item-divider>\n\n </ion-menu-toggle>\n </ion-list>\n </ion-content>\n\n <ion-footer class=\"hidden-xs hidden-sm\">\n <ion-toolbar>\n\n <ion-buttons slot=\"start\">\n <ion-button mat-icon-button color=\"accent\" (click)=\"openAboutModal($event)\">\n <mat-icon slot=\"icon-only\">help_outline</mat-icon>\n </ion-button>\n </ion-buttons>\n\n <ion-title (click)=\"openAboutModal($event)\" color=\"medium\">\n {{'MENU.FOOTER_VERSION_ABOUT'| translate: {version: appVersion} }}\n </ion-title>\n\n <ion-buttons slot=\"end\">\n <button mat-icon-button color=\"accent\" (click)=\"toggleSplitPaneShow($event)\"\n class=\"hidden-xs hidden-sm hidden-md\"\n [title]=\"(splitPane.when ? 'COMMON.BTN_HIDE_MENU' : 'COMMON.BTN_SHOW_MENU') |translate\">\n <mat-icon><span>{{splitPane.when ? '&#xab;' : '&#xbb;'}}</span></mat-icon>\n </button>\n </ion-buttons>\n </ion-toolbar>\n </ion-footer>\n\n </ion-menu>\n\n <ng-content></ng-content>\n\n</ion-split-pane>\n",
24756
+ 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",
24753
24757
  animations: [fadeInAnimation],
24754
24758
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
24755
24759
  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)}}"]
@@ -30172,48 +30176,63 @@
30172
30176
  var UserEventServiceToken = new i0.InjectionToken('UserEventService');
30173
30177
  var AbstractUserEventService = /** @class */ (function (_super) {
30174
30178
  __extends(AbstractUserEventService, _super);
30175
- function AbstractUserEventService(graphql, accountService, network, translate, toastController, queries, mutations, subscriptions, environment) {
30179
+ function AbstractUserEventService(graphql, accountService, network, translate, queries, mutations, subscriptions, environment) {
30176
30180
  var _this = _super.call(this, graphql, environment) || this;
30177
30181
  _this.graphql = graphql;
30178
30182
  _this.accountService = accountService;
30179
30183
  _this.network = network;
30180
30184
  _this.translate = translate;
30181
- _this.toastController = toastController;
30182
30185
  _this.queries = queries;
30183
30186
  _this.mutations = mutations;
30184
30187
  _this.subscriptions = subscriptions;
30185
30188
  _this.environment = environment;
30186
- _this._count$ = new rxjs.BehaviorSubject(0);
30187
- _this._subscriptions = new rxjs.Subscription();
30189
+ _this.count$ = new rxjs.BehaviorSubject(0);
30188
30190
  _this.listeners = [];
30191
+ _this._subscriptions = new rxjs.Subscription();
30189
30192
  _this._logPrefix = '[user-event-service] ';
30190
30193
  // For DEV only
30191
30194
  _this._debug = !(environment === null || environment === void 0 ? void 0 : environment.production);
30192
- // listen login/logout
30193
- _this._subscriptions.add(accountService.onLogin.subscribe(function () { return __awaiter(_this, void 0, void 0, function () {
30194
- var count;
30195
- return __generator(this, function (_b) {
30196
- switch (_b.label) {
30197
- case 0: return [4 /*yield*/, this.count(this.defaultFilter())];
30198
- case 1:
30199
- count = _b.sent();
30200
- if (count && this._debug) {
30201
- console.debug(this._logPrefix + "Received " + count + " unread notifications");
30202
- }
30203
- this._count$.next(count);
30204
- return [2 /*return*/];
30205
- }
30206
- });
30207
- }); }));
30208
30195
  return _this;
30209
30196
  }
30210
30197
  Object.defineProperty(AbstractUserEventService.prototype, "userEventCount", {
30211
30198
  get: function () {
30212
- return this._count$.asObservable();
30199
+ return this.count$.asObservable();
30213
30200
  },
30214
30201
  enumerable: false,
30215
30202
  configurable: true
30216
30203
  });
30204
+ AbstractUserEventService.prototype.ngOnStart = function () {
30205
+ return __awaiter(this, void 0, void 0, function () {
30206
+ var _this = this;
30207
+ return __generator(this, function (_b) {
30208
+ switch (_b.label) {
30209
+ case 0:
30210
+ // Update component when refresh is need (=login events)
30211
+ this._subscriptions.add(rxjs.merge(this.accountService.onLogin, this.accountService.onLogout)
30212
+ .pipe(
30213
+ // Wait account service ready (can be restarted)
30214
+ operators.mergeMap(function () { return _this.accountService.ready(); }), operators.map(function () { return _this.accountService.isLogin(); }), operators.distinctUntilChanged())
30215
+ .subscribe(function (login) {
30216
+ if (login) {
30217
+ _this.onLogin();
30218
+ }
30219
+ else {
30220
+ _this.onLogout();
30221
+ }
30222
+ }));
30223
+ // First attempt if account is ready
30224
+ return [4 /*yield*/, this.accountService.ready()];
30225
+ case 1:
30226
+ // First attempt if account is ready
30227
+ _b.sent();
30228
+ if (this.accountService.isLogin()) {
30229
+ setTimeout(function () { return _this.onLogin(); });
30230
+ }
30231
+ return [2 /*return*/];
30232
+ }
30233
+ });
30234
+ });
30235
+ };
30217
30236
  AbstractUserEventService.prototype.ngOnDestroy = function () {
30218
30237
  this._subscriptions.unsubscribe();
30219
30238
  };
@@ -30224,13 +30243,15 @@
30224
30243
  var _this = this;
30225
30244
  var _a;
30226
30245
  var now = this._debug && Date.now();
30227
- //if (this._debug)
30246
+ if (!filter) {
30247
+ filter = this.defaultFilter();
30248
+ }
30228
30249
  console.debug(this._logPrefix + "Loading user events...", filter);
30229
30250
  filter = this.asFilter(filter);
30230
30251
  // Force recipient to current issuer, if not admin and not specified
30231
- if (isEmptyArray(filter.recipients) || !this.accountService.isAdmin()) {
30252
+ if (isEmptyArray(filter === null || filter === void 0 ? void 0 : filter.recipients) || !this.accountService.isAdmin()) {
30232
30253
  var recipient = this.defaultRecipient();
30233
- if (!((_a = filter.recipients) === null || _a === void 0 ? void 0 : _a.includes(recipient))) {
30254
+ if (!((_a = filter === null || filter === void 0 ? void 0 : filter.recipients) === null || _a === void 0 ? void 0 : _a.includes(recipient))) {
30234
30255
  console.warn('[user-events-service] Force user event filter.recipient=' + recipient);
30235
30256
  filter.recipients = [recipient];
30236
30257
  }
@@ -30240,23 +30261,27 @@
30240
30261
  queryName: withContent ? 'LoadAllWithContent' : 'LoadAll',
30241
30262
  query: withContent ? this.queries.loadAllWithContent : this.queries.loadAll,
30242
30263
  variables: {
30243
- page: Object.assign({ sortBy: 'updateDate', sortDirection: 'desc' }, page),
30264
+ page: Object.assign(Object.assign({ sortBy: 'creationDate' }, page), {
30265
+ // @ts-ignore
30266
+ sortDirection: (page.sortDirection || 'desc').toUpperCase()
30267
+ }),
30244
30268
  filter: filter && filter.asPodObject()
30245
30269
  },
30246
30270
  arrayFieldName: 'data',
30247
30271
  error: { code: SocialErrorCodes.LOAD_USER_EVENTS_ERROR, message: 'SOCIAL.ERROR.LOAD_USER_EVENTS_ERROR' },
30248
- fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || "cache-first"
30272
+ fetchPolicy: (options === null || options === void 0 ? void 0 : options.fetchPolicy) || 'cache-first'
30249
30273
  })
30250
30274
  .pipe(operators.map(function (res) {
30251
- var data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(_this.processUserEvent);
30275
+ var data = ((res === null || res === void 0 ? void 0 : res.data) || []).map(function (value) { return _this.processUserEvent(value, _this); });
30252
30276
  if (now) {
30253
30277
  console.debug("" + _this._logPrefix + data.length + " user events loaded in " + (Date.now() - now) + "ms");
30254
30278
  now = null;
30255
30279
  }
30256
- var unreadCount = _this.unreadEvents(data);
30280
+ // Must re-order because of listenChanges result will add new event at the end
30281
+ data = EntityUtils.sort(data, page.sortBy, page.sortDirection);
30257
30282
  return {
30258
30283
  data: data,
30259
- total: toNumber(res === null || res === void 0 ? void 0 : res.total, unreadCount)
30284
+ total: toNumber(res === null || res === void 0 ? void 0 : res.total, data.length)
30260
30285
  };
30261
30286
  }));
30262
30287
  };
@@ -30270,7 +30295,7 @@
30270
30295
  data: entity
30271
30296
  });
30272
30297
  // Update count
30273
- this._count$.next(this._count$.value + 1);
30298
+ this.count$.next(this.count$.value + 1);
30274
30299
  };
30275
30300
  AbstractUserEventService.prototype.count = function (filter, options) {
30276
30301
  var _a;
@@ -30284,7 +30309,9 @@
30284
30309
  return [2 /*return*/, undefined];
30285
30310
  }
30286
30311
  if (!filter)
30287
- throw new Error("Missing argument 'filter'");
30312
+ filter = this.defaultFilter();
30313
+ // Apply last reset date as start date
30314
+ filter.startDate = this.resetCountDate;
30288
30315
  filter = this.asFilter(filter);
30289
30316
  if (this._debug)
30290
30317
  console.debug(this._logPrefix + "Counting user events with filter:", filter);
@@ -30303,6 +30330,37 @@
30303
30330
  });
30304
30331
  });
30305
30332
  };
30333
+ AbstractUserEventService.prototype.listenCountChanges = function (filter, options) {
30334
+ var _this = this;
30335
+ var _a;
30336
+ if (!((_a = this.subscriptions) === null || _a === void 0 ? void 0 : _a.listenCountChanges)) {
30337
+ console.warn(this._logPrefix + "Subscription query 'listenCountChanges' not provided, skip.");
30338
+ return rxjs.of();
30339
+ }
30340
+ if (!filter)
30341
+ filter = this.defaultFilter();
30342
+ // Apply last reset date as start date
30343
+ filter.startDate = this.resetCountDate;
30344
+ filter = this.asFilter(filter);
30345
+ if (this._debug)
30346
+ console.debug(this._logPrefix + "[WS] Listening count changes for user events with filter:", filter);
30347
+ return this.graphql.subscribe({
30348
+ query: this.subscriptions.listenCountChanges,
30349
+ fetchPolicy: options === null || options === void 0 ? void 0 : options.fetchPolicy,
30350
+ variables: { filter: filter.asPodObject(), interval: toNumber(options === null || options === void 0 ? void 0 : options.interval, 10) },
30351
+ error: {
30352
+ code: SocialErrorCodes.SUBSCRIBE_USER_EVENTS_ERROR,
30353
+ message: 'SOCIAL.ERROR.SUBSCRIBE_USER_EVENTS_ERROR'
30354
+ }
30355
+ }).pipe(operators.map(function (_b) {
30356
+ var total = _b.total;
30357
+ if (total && _this._debug)
30358
+ console.debug(_this._logPrefix + "Received new user events count:", total);
30359
+ // update count
30360
+ _this.count$.next(total);
30361
+ return total;
30362
+ }));
30363
+ };
30306
30364
  AbstractUserEventService.prototype.listenChanges = function (filter, options) {
30307
30365
  var _this = this;
30308
30366
  var _a;
@@ -30311,7 +30369,7 @@
30311
30369
  return rxjs.of();
30312
30370
  }
30313
30371
  if (!filter)
30314
- throw new Error("Missing argument 'filter'");
30372
+ filter = this.defaultFilter();
30315
30373
  filter = this.asFilter(filter);
30316
30374
  var withContent = (options === null || options === void 0 ? void 0 : options.withContent) === true;
30317
30375
  if (this._debug)
@@ -30328,14 +30386,12 @@
30328
30386
  var data = _b.data;
30329
30387
  if (data && _this._debug)
30330
30388
  console.debug(_this._logPrefix + "Received new user events:", data);
30331
- var updatedData = data === null || data === void 0 ? void 0 : data.map(_this.processUserEvent);
30389
+ var updatedData = data === null || data === void 0 ? void 0 : data.map(function (value) { return _this.processUserEvent(value, _this); });
30332
30390
  // Update cache
30333
30391
  _this.insertIntoMutableCachedQueries(_this.graphql.cache, {
30334
30392
  query: withContent ? _this.queries.loadAllWithContent : _this.queries.loadAll,
30335
30393
  data: updatedData
30336
30394
  });
30337
- // update count
30338
- _this._count$.next(_this.unreadEvents(updatedData));
30339
30395
  return updatedData;
30340
30396
  }));
30341
30397
  };
@@ -30396,13 +30452,13 @@
30396
30452
  };
30397
30453
  AbstractUserEventService.prototype.save = function (entity, options) {
30398
30454
  return __awaiter(this, void 0, void 0, function () {
30399
- var isNew, json, now;
30455
+ var withContent, json, now;
30400
30456
  var _this = this;
30401
30457
  return __generator(this, function (_b) {
30402
30458
  switch (_b.label) {
30403
30459
  case 0:
30404
30460
  this.fillDefaultProperties(entity);
30405
- isNew = isNil(entity.id);
30461
+ withContent = !!entity.content;
30406
30462
  json = entity.asObject();
30407
30463
  now = Date.now();
30408
30464
  if (this._debug)
@@ -30422,16 +30478,18 @@
30422
30478
  console.debug(_this._logPrefix + "User event saved in " + (Date.now() - now) + "ms", entity);
30423
30479
  _this.copyIdAndUpdateDate(savedEntity, entity);
30424
30480
  // Add to cache
30425
- if (isNew) {
30426
- _this.insertIntoMutableCachedQueries(proxy, {
30427
- query: _this.queries.loadAll,
30428
- data: Object.assign(Object.assign({}, savedEntity), { content: null })
30429
- });
30481
+ if (withContent) {
30430
30482
  _this.insertIntoMutableCachedQueries(proxy, {
30431
30483
  query: _this.queries.loadAllWithContent,
30432
30484
  data: savedEntity
30433
30485
  });
30434
30486
  }
30487
+ else {
30488
+ _this.insertIntoMutableCachedQueries(proxy, {
30489
+ query: _this.queries.loadAll,
30490
+ data: Object.assign(Object.assign({}, savedEntity), { content: null })
30491
+ });
30492
+ }
30435
30493
  }
30436
30494
  }
30437
30495
  })];
@@ -30442,55 +30500,100 @@
30442
30500
  });
30443
30501
  });
30444
30502
  };
30445
- AbstractUserEventService.prototype.saveAll = function (data, opts) {
30446
- var _this = this;
30447
- return Promise.all(data
30448
- .map(function (entity) { return _this.save(entity, opts); }));
30503
+ AbstractUserEventService.prototype.saveAll = function (entities, opts) {
30504
+ return __awaiter(this, void 0, void 0, function () {
30505
+ var _this = this;
30506
+ return __generator(this, function (_b) {
30507
+ return [2 /*return*/, Promise.all(entities
30508
+ .map(function (entity) { return _this.save(entity, opts); }))];
30509
+ });
30510
+ });
30449
30511
  };
30450
- AbstractUserEventService.prototype.markAsRead = function (entity) {
30512
+ AbstractUserEventService.prototype.markAsRead = function (entities) {
30451
30513
  return __awaiter(this, void 0, void 0, function () {
30452
- var onReadListeners, onReadListeners_1, onReadListeners_1_1, listener, e_1_1;
30453
- var e_1, _b;
30454
- return __generator(this, function (_c) {
30455
- switch (_c.label) {
30514
+ var userEventWithoutReadListeners, _loop_1, this_1, _b, _c, entity, e_1_1;
30515
+ var e_1, _d;
30516
+ return __generator(this, function (_e) {
30517
+ switch (_e.label) {
30456
30518
  case 0:
30457
- onReadListeners = (this.listeners || []).filter(function (listener) { return !!listener.onRead; }).filter(function (listener) { return listener.accept(entity); });
30458
- if (!onReadListeners.length) return [3 /*break*/, 9];
30459
- _c.label = 1;
30519
+ userEventWithoutReadListeners = [];
30520
+ _loop_1 = function (entity) {
30521
+ var onReadListeners, onReadListeners_1, onReadListeners_1_1, listener, e_2_1;
30522
+ var e_2, _b;
30523
+ return __generator(this, function (_c) {
30524
+ switch (_c.label) {
30525
+ case 0:
30526
+ onReadListeners = (this_1.listeners || []).filter(function (listener) { return !!listener.onRead; }).filter(function (listener) { return listener.accept(entity); });
30527
+ if (!onReadListeners.length) return [3 /*break*/, 9];
30528
+ _c.label = 1;
30529
+ case 1:
30530
+ _c.trys.push([1, 6, 7, 8]);
30531
+ onReadListeners_1 = (e_2 = void 0, __values(onReadListeners)), onReadListeners_1_1 = onReadListeners_1.next();
30532
+ _c.label = 2;
30533
+ case 2:
30534
+ if (!!onReadListeners_1_1.done) return [3 /*break*/, 5];
30535
+ listener = onReadListeners_1_1.value;
30536
+ return [4 /*yield*/, listener.onRead(entity)];
30537
+ case 3:
30538
+ _c.sent();
30539
+ _c.label = 4;
30540
+ case 4:
30541
+ onReadListeners_1_1 = onReadListeners_1.next();
30542
+ return [3 /*break*/, 2];
30543
+ case 5: return [3 /*break*/, 8];
30544
+ case 6:
30545
+ e_2_1 = _c.sent();
30546
+ e_2 = { error: e_2_1 };
30547
+ return [3 /*break*/, 8];
30548
+ case 7:
30549
+ try {
30550
+ if (onReadListeners_1_1 && !onReadListeners_1_1.done && (_b = onReadListeners_1.return)) _b.call(onReadListeners_1);
30551
+ }
30552
+ finally { if (e_2) throw e_2.error; }
30553
+ return [7 /*endfinally*/];
30554
+ case 8: return [3 /*break*/, 10];
30555
+ case 9:
30556
+ // Add to this list for default operation
30557
+ userEventWithoutReadListeners.push(entity);
30558
+ _c.label = 10;
30559
+ case 10: return [2 /*return*/];
30560
+ }
30561
+ });
30562
+ };
30563
+ this_1 = this;
30564
+ _e.label = 1;
30460
30565
  case 1:
30461
- _c.trys.push([1, 6, 7, 8]);
30462
- onReadListeners_1 = __values(onReadListeners), onReadListeners_1_1 = onReadListeners_1.next();
30463
- _c.label = 2;
30566
+ _e.trys.push([1, 6, 7, 8]);
30567
+ _b = __values((entities || [])), _c = _b.next();
30568
+ _e.label = 2;
30464
30569
  case 2:
30465
- if (!!onReadListeners_1_1.done) return [3 /*break*/, 5];
30466
- listener = onReadListeners_1_1.value;
30467
- return [4 /*yield*/, listener.onRead(entity)];
30570
+ if (!!_c.done) return [3 /*break*/, 5];
30571
+ entity = _c.value;
30572
+ return [5 /*yield**/, _loop_1(entity)];
30468
30573
  case 3:
30469
- _c.sent();
30470
- _c.label = 4;
30574
+ _e.sent();
30575
+ _e.label = 4;
30471
30576
  case 4:
30472
- onReadListeners_1_1 = onReadListeners_1.next();
30577
+ _c = _b.next();
30473
30578
  return [3 /*break*/, 2];
30474
30579
  case 5: return [3 /*break*/, 8];
30475
30580
  case 6:
30476
- e_1_1 = _c.sent();
30581
+ e_1_1 = _e.sent();
30477
30582
  e_1 = { error: e_1_1 };
30478
30583
  return [3 /*break*/, 8];
30479
30584
  case 7:
30480
30585
  try {
30481
- if (onReadListeners_1_1 && !onReadListeners_1_1.done && (_b = onReadListeners_1.return)) _b.call(onReadListeners_1);
30586
+ if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
30482
30587
  }
30483
30588
  finally { if (e_1) throw e_1.error; }
30484
30589
  return [7 /*endfinally*/];
30485
- case 8: return [3 /*break*/, 11];
30486
- case 9:
30590
+ case 8:
30487
30591
  // Use default
30488
- return [4 /*yield*/, this.defaultMarkAsRead(entity)];
30489
- case 10:
30592
+ return [4 /*yield*/, this.defaultMarkAsRead(userEventWithoutReadListeners)];
30593
+ case 9:
30490
30594
  // Use default
30491
- _c.sent();
30492
- _c.label = 11;
30493
- case 11: return [2 /*return*/];
30595
+ _e.sent();
30596
+ return [2 /*return*/];
30494
30597
  }
30495
30598
  });
30496
30599
  });
@@ -30500,13 +30603,51 @@
30500
30603
  this.listeners = [];
30501
30604
  this.listeners.push(listener);
30502
30605
  };
30606
+ AbstractUserEventService.prototype.resetCount = function () {
30607
+ this.count$.next(undefined);
30608
+ this.resetCountDate = moment$6();
30609
+ // restart listening count changes
30610
+ this.startListenCountChanges();
30611
+ };
30503
30612
  /* -- protected methods -- */
30504
- AbstractUserEventService.prototype.processUserEvent = function (source) {
30505
- var e_2, _b;
30613
+ AbstractUserEventService.prototype.onLogin = function () {
30614
+ return __awaiter(this, void 0, void 0, function () {
30615
+ var count;
30616
+ return __generator(this, function (_b) {
30617
+ switch (_b.label) {
30618
+ case 0: return [4 /*yield*/, this.count(undefined)];
30619
+ case 1:
30620
+ count = _b.sent();
30621
+ if (this._debug)
30622
+ console.debug(this._logPrefix + "Receiving user events count", count);
30623
+ // Update count
30624
+ this.count$.next(count);
30625
+ // Then listen changes
30626
+ this.startListenCountChanges();
30627
+ return [2 /*return*/];
30628
+ }
30629
+ });
30630
+ });
30631
+ };
30632
+ AbstractUserEventService.prototype.onLogout = function () {
30633
+ this.stopListenCountChanges();
30634
+ };
30635
+ AbstractUserEventService.prototype.startListenCountChanges = function () {
30636
+ this.stopListenCountChanges();
30637
+ this._listenSubscription = this.listenCountChanges(undefined).subscribe();
30638
+ };
30639
+ AbstractUserEventService.prototype.stopListenCountChanges = function () {
30640
+ var _a;
30641
+ (_a = this._listenSubscription) === null || _a === void 0 ? void 0 : _a.unsubscribe();
30642
+ this._listenSubscription = undefined;
30643
+ };
30644
+ AbstractUserEventService.prototype.processUserEvent = function (source, that) {
30645
+ var e_3, _b;
30646
+ that = that || this;
30506
30647
  // Convert json source to IUserEvent
30507
- var target = this.fromObject(source);
30648
+ var target = that.fromObject(source);
30508
30649
  // Get listeners
30509
- var listeners = (this.listeners || []).filter(function (listener) { return listener.onReceived; }).filter(function (listener) { return listener.accept(target); });
30650
+ var listeners = (that.listeners || []).filter(function (listener) { return listener.onReceived; }).filter(function (listener) { return listener.accept(target); });
30510
30651
  try {
30511
30652
  for (var listeners_1 = __values(listeners), listeners_1_1 = listeners_1.next(); !listeners_1_1.done; listeners_1_1 = listeners_1.next()) {
30512
30653
  var listener = listeners_1_1.value;
@@ -30514,39 +30655,64 @@
30514
30655
  target = listener.onReceived(target);
30515
30656
  }
30516
30657
  else {
30517
- if (this._debug)
30518
- console.debug(this._logPrefix + "Event has been rejected by a listener", source);
30658
+ if (that._debug)
30659
+ console.debug(that._logPrefix + "Event has been rejected by a listener", source);
30519
30660
  break;
30520
30661
  }
30521
30662
  }
30522
30663
  }
30523
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
30664
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
30524
30665
  finally {
30525
30666
  try {
30526
30667
  if (listeners_1_1 && !listeners_1_1.done && (_b = listeners_1.return)) _b.call(listeners_1);
30527
30668
  }
30528
- finally { if (e_2) throw e_2.error; }
30669
+ finally { if (e_3) throw e_3.error; }
30529
30670
  }
30530
30671
  return target;
30531
30672
  };
30532
- AbstractUserEventService.prototype.defaultMarkAsRead = function (userEvent) {
30673
+ AbstractUserEventService.prototype.defaultMarkAsRead = function (userEvents) {
30674
+ var _a;
30533
30675
  return __awaiter(this, void 0, void 0, function () {
30676
+ var localEntities, remoteEntities, ids, now;
30534
30677
  return __generator(this, function (_b) {
30535
30678
  switch (_b.label) {
30536
30679
  case 0:
30537
- if (!userEvent)
30680
+ if (!userEvents)
30538
30681
  throw new Error(this._logPrefix + "Invalid event to save");
30682
+ if (!userEvents.length)
30683
+ return [2 /*return*/];
30539
30684
  // set read date
30540
- userEvent.readDate = moment$6();
30541
- if (!(!userEvent.id || userEvent.id < 0)) return [3 /*break*/, 1];
30685
+ userEvents.forEach(function (userEvent) { return userEvent.readDate = moment$6(); });
30686
+ localEntities = userEvents.filter(function (userEvent) { return !userEvent.id || userEvent.id < 0; });
30687
+ remoteEntities = userEvents.filter(function (userEvent) { return userEvent.id > 0; });
30688
+ // save local entities
30689
+ if (localEntities.length) {
30690
+ if (this._debug)
30691
+ console.debug(this._logPrefix + "Save local user event");
30692
+ // TODO !!!!!!!!!!!!!
30693
+ }
30694
+ if (!remoteEntities.length) return [3 /*break*/, 2];
30695
+ if (!((_a = this.mutations) === null || _a === void 0 ? void 0 : _a.markAsRead)) {
30696
+ console.warn(this._logPrefix + "Mutation query 'markAsRead' not provided, skip.");
30697
+ return [2 /*return*/];
30698
+ }
30699
+ ids = remoteEntities.map(function (value) { return value.id; });
30700
+ now = Date.now();
30542
30701
  if (this._debug)
30543
- console.debug(this._logPrefix + "Save local user event");
30544
- return [3 /*break*/, 3];
30545
- case 1: return [4 /*yield*/, this.save(userEvent)];
30546
- case 2:
30702
+ console.debug(this._logPrefix + "Mark user events as read...", ids);
30703
+ return [4 /*yield*/, this.graphql.mutate({
30704
+ mutation: this.mutations.markAsRead,
30705
+ variables: {
30706
+ ids: ids
30707
+ },
30708
+ error: { code: SocialErrorCodes.SAVE_USER_EVENT_ERROR, message: 'SOCIAL.ERROR.SAVE_USER_EVENT_ERROR' },
30709
+ })];
30710
+ case 1:
30547
30711
  _b.sent();
30548
- _b.label = 3;
30549
- case 3: return [2 /*return*/];
30712
+ if (this._debug)
30713
+ console.debug(this._logPrefix + "User events marked as read in " + (Date.now() - now) + "ms", ids);
30714
+ _b.label = 2;
30715
+ case 2: return [2 /*return*/];
30550
30716
  }
30551
30717
  });
30552
30718
  });
@@ -30585,7 +30751,6 @@
30585
30751
  { type: AccountService },
30586
30752
  { type: NetworkService },
30587
30753
  { type: i1$2.TranslateService },
30588
- { type: i1$5.ToastController },
30589
30754
  { type: undefined },
30590
30755
  { type: undefined },
30591
30756
  { type: undefined },
@@ -30602,7 +30767,7 @@
30602
30767
  var UserEventService = /** @class */ (function (_super) {
30603
30768
  __extends(UserEventService, _super);
30604
30769
  function UserEventService(graphql, accountService, network, translate, toastController, environment) {
30605
- var _this = _super.call(this, graphql, accountService, network, translate, toastController, userEventQueries, userEventMutations, undefined, environment) || this;
30770
+ var _this = _super.call(this, graphql, accountService, network, translate, userEventQueries, userEventMutations, undefined, environment) || this;
30606
30771
  _this.graphql = graphql;
30607
30772
  _this.accountService = accountService;
30608
30773
  _this.network = network;
@@ -30899,7 +31064,7 @@
30899
31064
  UserEventsTable.decorators = [
30900
31065
  { type: i0.Component, args: [{
30901
31066
  selector: 'app-user-events-table',
30902
- template: "\n<!-- Type = options menu -->\n<mat-menu #optionsMenu=\"matMenu\" xPosition=\"after\">\n\n <!-- display columns -->\n <button mat-menu-item\n (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n</mat-menu>\n\n<!-- top header -->\n<mat-toolbar>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n\n <button mat-icon-button [title]=\"'COMMON.BTN_REFRESH'|translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\n\n <!-- delete -->\n <button mat-icon-button class=\"hidden-xs hidden-sm\" *ngIf=\"canDelete\"\n [title]=\"'COMMON.BTN_DELETE'|translate\" (click)=\"deleteSelection($event)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" hidden-xs hidden-sm hidden-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS'|translate\"\n [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n</mat-toolbar>\n\n\n<mat-table [dataSource]=\"dataSource\" matSort\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear [trackBy]=\"trackByFn\">\n\n <!-- select -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\" [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <!-- id -->\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef mat-sort-header [class.cdk-visually-hidden]=\"!isAdmin\">\n <app-loading-spinner [loading]=\"loadingSubject|async\"><ion-label>#</ion-label></app-loading-spinner>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!isAdmin\">{{ row.currentData.id | mathAbs }}</mat-cell>\n </ng-container>\n\n <!-- creationDate -->\n <ng-container matColumnDef=\"creationDate\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.CREATION_DATE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ion-text>\n {{row.currentData.creationDate | dateFromNow }}<br/>\n <ion-text color=\"medium\"><small>{{row.currentData.creationDate | dateFormat: {time: true} }}</small></ion-text>\n </ion-text>\n </mat-cell>\n </ng-container>\n\n <!-- icon -->\n <ng-container matColumnDef=\"icon\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getIcon(row.currentData); let details\">\n <ion-icon slot=\"start\" *ngIf=\"details.icon\" [name]=\"details.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"details.matIcon\">{{details.matIcon}}</mat-icon>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- event type -->\n <ng-container matColumnDef=\"eventType\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.EVENT_TYPE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <span>{{'SOCIAL.USER_EVENT.TYPE_ENUM.' + row.currentData.eventType | translate}}</span>\n </mat-cell>\n </ng-container>\n\n <!-- message -->\n <ng-container matColumnDef=\"message\">\n <mat-header-cell *matHeaderCellDef>\n <ion-label translate>SOCIAL.USER_EVENT.MESSAGE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <ion-text [innerHTML]=\"details.title|translate\">\n </ion-text>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- Actions buttons column -->\n <ng-container matColumnDef=\"actions\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <button mat-icon-button color=\"light\"\n *ngFor=\"let action of details.actions\"\n [title]=\"action.title |translate\"\n [color]=\"action.color\"\n (click)=\"doAction(action, row)\">\n <ion-icon slot=\"start\" *ngIf=\"action.icon\" [name]=\"action.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"action.matIcon\">{{action.matIcon}}</mat-icon>\n </button>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n class=\"mat-row-disabled\"\n (click)=\"clickRow($event, row)\"></mat-row>\n\n</mat-table>\n\n<ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col class=\"ion-no-padding\" size=\"auto\">\n <mat-paginator [length]=\"totalRowCount\" [pageSize]=\"defaultPageSize\" [pageSizeOptions]=\"defaultPageSizeOptions\" showFirstLastButtons>\n </mat-paginator>\n </ion-col>\n</ion-row>\n",
31067
+ template: "\n<!-- Type = options menu -->\n<mat-menu #optionsMenu=\"matMenu\" xPosition=\"after\">\n\n <!-- display columns -->\n <button mat-menu-item\n (click)=\"openSelectColumnsModal($event)\">\n <mat-icon>view_column</mat-icon>\n <ion-label translate>COMMON.DISPLAYED_COLUMNS_DOTS</ion-label>\n </button>\n\n</mat-menu>\n\n<!-- top header -->\n<mat-toolbar>\n\n <ng-container *ngIf=\"!selection.hasValue(); else hasSelection\">\n\n <button mat-icon-button [title]=\"'COMMON.BTN_REFRESH'|translate\" (click)=\"onRefresh.emit()\">\n <mat-icon>refresh</mat-icon>\n </button>\n\n </ng-container>\n\n <!-- if row selection -->\n <ng-template #hasSelection>\n\n <!-- delete -->\n <button mat-icon-button class=\"hidden-xs hidden-sm\" *ngIf=\"canDelete\"\n [title]=\"'COMMON.BTN_DELETE'|translate\" (click)=\"deleteSelection($event)\">\n <mat-icon>delete</mat-icon>\n </button>\n </ng-template>\n\n <!-- error -->\n <ion-item *ngIf=\"error\" hidden-xs hidden-sm hidden-mobile lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error|translate\"></ion-label>\n </ion-item>\n\n <div class=\"toolbar-spacer\"></div>\n\n <button mat-icon-button\n [title]=\"'COMMON.BTN_OPTIONS'|translate\"\n [matMenuTriggerFor]=\"optionsMenu\">\n <mat-icon>more_vert</mat-icon>\n </button>\n</mat-toolbar>\n\n\n<mat-table [dataSource]=\"dataSource\" matSort\n [matSortActive]=\"defaultSortBy\"\n [matSortDirection]=\"defaultSortDirection\"\n matSortDisableClear [trackBy]=\"trackByFn\">\n\n <!-- select -->\n <ng-container matColumnDef=\"select\">\n <mat-header-cell *matHeaderCellDef [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (change)=\"$event ? masterToggle() : null\" [checked]=\"selection.hasValue() && isAllSelected()\"\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\">\n </mat-checkbox>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!canEdit\">\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? selection.toggle(row) : null\" [checked]=\"selection.isSelected(row)\">\n </mat-checkbox>\n </mat-cell>\n </ng-container>\n\n <!-- id -->\n <ng-container matColumnDef=\"id\">\n <mat-header-cell *matHeaderCellDef mat-sort-header [class.cdk-visually-hidden]=\"!isAdmin\">\n <app-loading-spinner [loading]=\"loadingSubject|async\"><ion-label>#</ion-label></app-loading-spinner>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\" [class.cdk-visually-hidden]=\"!isAdmin\">{{ row.currentData.id | mathAbs }}</mat-cell>\n </ng-container>\n\n <!-- creationDate -->\n <ng-container matColumnDef=\"creationDate\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.CREATION_DATE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ion-text>\n {{row.currentData.creationDate | dateFromNow }}<br/>\n <ion-text color=\"medium\"><small>{{row.currentData.creationDate | dateFormat: {time: true} }}</small></ion-text>\n </ion-text>\n </mat-cell>\n </ng-container>\n\n <!-- icon -->\n <ng-container matColumnDef=\"icon\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getIcon(row.currentData); let details\">\n <ion-icon slot=\"start\" *ngIf=\"details.icon\" [name]=\"details.icon\"></ion-icon>\n <mat-icon slot=\"start\" *ngIf=\"details.matIcon\">{{details.matIcon}}</mat-icon>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- event type -->\n <ng-container matColumnDef=\"eventType\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>\n <ion-label translate>SOCIAL.USER_EVENT.EVENT_TYPE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <span>{{'SOCIAL.USER_EVENT.TYPE_ENUM.' + row.currentData.eventType | translate}}</span>\n </mat-cell>\n </ng-container>\n\n <!-- message -->\n <ng-container matColumnDef=\"message\">\n <mat-header-cell *matHeaderCellDef>\n <ion-label translate>SOCIAL.USER_EVENT.MESSAGE</ion-label>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row;\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <ion-text [innerHTML]=\"details.title|translate\">\n </ion-text>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <!-- Actions buttons column -->\n <ng-container matColumnDef=\"actions\">\n <mat-header-cell *matHeaderCellDef>\n </mat-header-cell>\n <mat-cell *matCellDef=\"let row\">\n <ng-container *ngIf=\"getDetail(row.currentData); let details\">\n <button mat-icon-button color=\"light\"\n *ngFor=\"let action of details.actions\"\n [title]=\"action.title |translate\"\n [color]=\"action.color\"\n (click)=\"doAction(action, row)\">\n <app-icon slot=\"start\" *ngIf=\"action.iconRef\" [ref]=\"action.iconRef\"></app-icon>\n </button>\n </ng-container>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n class=\"mat-row-disabled\"\n (click)=\"clickRow($event, row)\"></mat-row>\n\n</mat-table>\n\n<ion-row class=\"ion-no-padding\">\n <ion-col></ion-col>\n <ion-col class=\"ion-no-padding\" size=\"auto\">\n <mat-paginator [length]=\"totalRowCount\" [pageSize]=\"defaultPageSize\" [pageSizeOptions]=\"defaultPageSizeOptions\" showFirstLastButtons>\n </mat-paginator>\n </ion-col>\n</ion-row>\n",
30903
31068
  changeDetection: i0.ChangeDetectionStrategy.OnPush,
30904
31069
  providers: [
30905
31070
  {
@@ -30925,17 +31090,48 @@
30925
31090
  };
30926
31091
 
30927
31092
  var UserEventNotificationList = /** @class */ (function () {
30928
- function UserEventNotificationList(popoverController) {
31093
+ function UserEventNotificationList(cd, popoverController, userEventService) {
31094
+ this.cd = cd;
30929
31095
  this.popoverController = popoverController;
31096
+ this.userEventService = userEventService;
31097
+ this.debug = false;
31098
+ this.userEvents = new rxjs.BehaviorSubject(undefined);
31099
+ this.subscriptions = new rxjs.Subscription();
30930
31100
  }
30931
31101
  UserEventNotificationList.prototype.ngOnInit = function () {
31102
+ var _this = this;
31103
+ // Watch all user events
31104
+ this.subscriptions.add(this.userEventService
31105
+ .watchAll(0, 10, 'creationDate', "desc", undefined)
31106
+ .subscribe(function (result) {
31107
+ if (_this.debug)
31108
+ console.debug("[user-event-notification-list] receiving " + result.total + " user events", result.data);
31109
+ _this.userEvents.next(result.data);
31110
+ _this.markForCheck();
31111
+ }));
31112
+ // Listen changes
31113
+ this.subscriptions.add(this.userEventService.listenChanges(undefined)
31114
+ .subscribe(function (data) {
31115
+ if (_this.debug)
31116
+ console.debug("[user-event-notification-list] receiving " + data.length + " new user events", data);
31117
+ }));
31118
+ };
31119
+ UserEventNotificationList.prototype.ngOnDestroy = function () {
31120
+ this.subscriptions.unsubscribe();
30932
31121
  };
30933
- UserEventNotificationList.prototype.read = function ($event, userEvent) {
31122
+ UserEventNotificationList.prototype.read = function (event, userEvent) {
30934
31123
  var _a;
30935
31124
  if (userEvent === null || userEvent === void 0 ? void 0 : userEvent.readDate)
30936
31125
  return;
30937
31126
  (_a = this.readEvent) === null || _a === void 0 ? void 0 : _a.emit(userEvent);
30938
31127
  };
31128
+ UserEventNotificationList.prototype.readAll = function (event) {
31129
+ var _a;
31130
+ var unreadUserEvents = (this.userEvents.value || []).filter(function (value) { return !value.readDate; });
31131
+ if (!unreadUserEvents.length)
31132
+ return;
31133
+ (_a = this.readEvents) === null || _a === void 0 ? void 0 : _a.emit(unreadUserEvents);
31134
+ };
30939
31135
  UserEventNotificationList.prototype.executeAction = function (action, userEvent) {
30940
31136
  // Execute then close popover
30941
31137
  action.executeAction(userEvent);
@@ -30944,37 +31140,42 @@
30944
31140
  UserEventNotificationList.prototype.dismiss = function () {
30945
31141
  this.popoverController.dismiss();
30946
31142
  };
31143
+ UserEventNotificationList.prototype.markForCheck = function () {
31144
+ this.cd.markForCheck();
31145
+ };
30947
31146
  return UserEventNotificationList;
30948
31147
  }());
30949
31148
  UserEventNotificationList.decorators = [
30950
31149
  { type: i0.Component, args: [{
30951
31150
  selector: 'app-user-event-notification-list',
30952
- 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",
30953
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}.unread{font-weight:700}"]
31151
+ 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\">\n <a (click)=\"readAll($event)\">{{'SOCIAL.USER_EVENT.NOTIFICATION.READ_ALL' | translate}}</a>\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 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",
31152
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
31153
+ styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-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:#f5f5f5;font-style:italic}.action a{margin-right:10px;cursor:pointer}.action app-icon{vertical-align:middle}"]
30954
31154
  },] }
30955
31155
  ];
30956
31156
  UserEventNotificationList.ctorParameters = function () { return [
30957
- { type: i1$5.PopoverController }
31157
+ { type: i0.ChangeDetectorRef },
31158
+ { type: i1$5.PopoverController },
31159
+ { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [UserEventServiceToken,] }] }
30958
31160
  ]; };
30959
31161
  UserEventNotificationList.propDecorators = {
31162
+ debug: [{ type: i0.Input }],
30960
31163
  titleI18n: [{ type: i0.Input }],
30961
- userEvents: [{ type: i0.Input }],
30962
- readEvent: [{ type: i0.Output }]
31164
+ readEvent: [{ type: i0.Output }],
31165
+ readEvents: [{ type: i0.Output }]
30963
31166
  };
30964
31167
 
30965
31168
  var UserEventNotificationComponent = /** @class */ (function () {
30966
- function UserEventNotificationComponent(userEventService, accountService, popoverController, cd) {
31169
+ function UserEventNotificationComponent(userEventService, accountService, popoverController) {
30967
31170
  this.userEventService = userEventService;
30968
31171
  this.accountService = accountService;
30969
31172
  this.popoverController = popoverController;
30970
- this.cd = cd;
30971
31173
  this.debug = false;
30972
31174
  this.titleI18n = 'SOCIAL.USER_EVENT.NOTIFICATION.TITLE';
30973
31175
  this.disabled = false;
30974
- this.userEventsSubject = new rxjs.BehaviorSubject(undefined);
30975
- this._subscriptions = new rxjs.Subscription();
30976
31176
  this._logPrefix = '[user-event-notification] ';
30977
31177
  this._readEvent = new i0.EventEmitter();
31178
+ this._readEvents = new i0.EventEmitter();
30978
31179
  }
30979
31180
  Object.defineProperty(UserEventNotificationComponent.prototype, "count", {
30980
31181
  get: function () {
@@ -30985,24 +31186,24 @@
30985
31186
  configurable: true
30986
31187
  });
30987
31188
  UserEventNotificationComponent.prototype.ngOnInit = function () {
30988
- var _this = this;
30989
- var _a;
30990
- if (isNil(this.userEventService)) {
30991
- console.warn(this._logPrefix + "No service injected");
30992
- this.disabled = true;
30993
- return;
30994
- }
30995
- this._subscriptions.add(this.userEventService.watchAll(0, 10, 'creationDate', "desc", {
30996
- recipients: [(_a = this.accountService.person) === null || _a === void 0 ? void 0 : _a.pubkey]
30997
- }).subscribe(function (value) {
30998
- var data = value.data;
30999
- if (_this.debug) {
31000
- console.debug(_this._logPrefix + "Receiving user events", data);
31001
- }
31002
- _this.userEventsSubject.next(data);
31003
- }));
31004
- this._readEvent.subscribe(function (value) {
31005
- _this.userEventService.markAsRead(value);
31189
+ return __awaiter(this, void 0, void 0, function () {
31190
+ var _this = this;
31191
+ return __generator(this, function (_b) {
31192
+ if (isNil(this.userEventService)) {
31193
+ console.warn(this._logPrefix + "No service injected");
31194
+ this.disabled = true;
31195
+ return [2 /*return*/];
31196
+ }
31197
+ // Subscribe to read event
31198
+ this._readEvent.subscribe(function (value) {
31199
+ // default: mark event as read
31200
+ _this.userEventService.markAsRead([value]);
31201
+ });
31202
+ this._readEvents.subscribe(function (value) {
31203
+ _this.userEventService.markAsRead(value);
31204
+ });
31205
+ return [2 /*return*/];
31206
+ });
31006
31207
  });
31007
31208
  };
31008
31209
  UserEventNotificationComponent.prototype.showList = function (event) {
@@ -31010,19 +31211,23 @@
31010
31211
  var popover;
31011
31212
  return __generator(this, function (_b) {
31012
31213
  switch (_b.label) {
31013
- case 0: return [4 /*yield*/, this.popoverController.create({
31014
- component: UserEventNotificationList,
31015
- componentProps: {
31016
- titleI18n: this.titleI18n,
31017
- userEvents: this.userEventsSubject,
31018
- readEvent: this._readEvent
31019
- },
31020
- backdropDismiss: true,
31021
- keyboardClose: true,
31022
- event: event,
31023
- translucent: true,
31024
- cssClass: 'popover-large'
31025
- })];
31214
+ case 0:
31215
+ // Reset count
31216
+ this.userEventService.resetCount();
31217
+ return [4 /*yield*/, this.popoverController.create({
31218
+ component: UserEventNotificationList,
31219
+ componentProps: {
31220
+ debug: this.debug,
31221
+ titleI18n: this.titleI18n,
31222
+ readEvent: this._readEvent,
31223
+ readEvents: this._readEvents
31224
+ },
31225
+ backdropDismiss: true,
31226
+ keyboardClose: true,
31227
+ event: event,
31228
+ translucent: true,
31229
+ cssClass: 'popover-large'
31230
+ })];
31026
31231
  case 1:
31027
31232
  popover = _b.sent();
31028
31233
  return [4 /*yield*/, popover.present()];
@@ -31033,14 +31238,10 @@
31033
31238
  });
31034
31239
  });
31035
31240
  };
31036
- UserEventNotificationComponent.prototype.markForCheck = function () {
31037
- this.cd.markForCheck();
31038
- };
31039
31241
  UserEventNotificationComponent.prototype.ngOnDestroy = function () {
31040
31242
  if (this.debug) {
31041
31243
  console.debug(this._logPrefix + "Destroying");
31042
31244
  }
31043
- this._subscriptions.unsubscribe();
31044
31245
  };
31045
31246
  return UserEventNotificationComponent;
31046
31247
  }());
@@ -31055,8 +31256,7 @@
31055
31256
  UserEventNotificationComponent.ctorParameters = function () { return [
31056
31257
  { type: undefined, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [UserEventServiceToken,] }] },
31057
31258
  { type: AccountService },
31058
- { type: i1$5.PopoverController },
31059
- { type: i0.ChangeDetectorRef }
31259
+ { type: i1$5.PopoverController }
31060
31260
  ]; };
31061
31261
  UserEventNotificationComponent.propDecorators = {
31062
31262
  debug: [{ type: i0.Input }],
@@ -31064,6 +31264,100 @@
31064
31264
  disabled: [{ type: i0.Input }]
31065
31265
  };
31066
31266
 
31267
+ var UserEventTestService = /** @class */ (function (_super) {
31268
+ __extends(UserEventTestService, _super);
31269
+ function UserEventTestService(graphql, accountService, network, translate, environment) {
31270
+ var _this = _super.call(this, graphql, accountService, network, translate, undefined, undefined, undefined, environment) || this;
31271
+ _this.graphql = graphql;
31272
+ _this.accountService = accountService;
31273
+ _this.network = network;
31274
+ _this.translate = translate;
31275
+ _this.environment = environment;
31276
+ _this.userEvents = [];
31277
+ return _this;
31278
+ }
31279
+ UserEventTestService.prototype.fromObject = function (source) {
31280
+ return exports.UserEvent.fromObject(source);
31281
+ };
31282
+ UserEventTestService.prototype.add = function (entity) {
31283
+ entity = this.processUserEvent(entity);
31284
+ entity.id = this.userEvents.length + 1;
31285
+ this.userEvents.push(entity);
31286
+ this.count$.next(this.userEvents.length);
31287
+ };
31288
+ UserEventTestService.prototype.asFilter = function (filter) {
31289
+ return filter;
31290
+ };
31291
+ UserEventTestService.prototype.count = function (filter, options) {
31292
+ return Promise.resolve(this.userEvents.length);
31293
+ };
31294
+ UserEventTestService.prototype.delete = function (entity) {
31295
+ return Promise.resolve(undefined);
31296
+ };
31297
+ UserEventTestService.prototype.deleteAll = function (data, opts) {
31298
+ return Promise.resolve(undefined);
31299
+ };
31300
+ UserEventTestService.prototype.listenChanges = function (filter, options) {
31301
+ return rxjs.of();
31302
+ };
31303
+ UserEventTestService.prototype.save = function (entity, options) {
31304
+ var _a;
31305
+ var toSave = (_a = this.userEvents) === null || _a === void 0 ? void 0 : _a.find(function (value) { return value.id == (entity === null || entity === void 0 ? void 0 : entity.id); });
31306
+ Object.assign(toSave, entity);
31307
+ return entity;
31308
+ };
31309
+ UserEventTestService.prototype.saveAll = function (data, opts) {
31310
+ return __awaiter(this, void 0, void 0, function () {
31311
+ var _b, _c, entity, e_1_1;
31312
+ var e_1, _d;
31313
+ return __generator(this, function (_e) {
31314
+ switch (_e.label) {
31315
+ case 0:
31316
+ _e.trys.push([0, 5, 6, 7]);
31317
+ _b = __values((data || [])), _c = _b.next();
31318
+ _e.label = 1;
31319
+ case 1:
31320
+ if (!!_c.done) return [3 /*break*/, 4];
31321
+ entity = _c.value;
31322
+ return [4 /*yield*/, this.save(entity)];
31323
+ case 2:
31324
+ _e.sent();
31325
+ _e.label = 3;
31326
+ case 3:
31327
+ _c = _b.next();
31328
+ return [3 /*break*/, 1];
31329
+ case 4: return [3 /*break*/, 7];
31330
+ case 5:
31331
+ e_1_1 = _e.sent();
31332
+ e_1 = { error: e_1_1 };
31333
+ return [3 /*break*/, 7];
31334
+ case 6:
31335
+ try {
31336
+ if (_c && !_c.done && (_d = _b.return)) _d.call(_b);
31337
+ }
31338
+ finally { if (e_1) throw e_1.error; }
31339
+ return [7 /*endfinally*/];
31340
+ case 7: return [2 /*return*/, Promise.resolve(this.userEvents)];
31341
+ }
31342
+ });
31343
+ });
31344
+ };
31345
+ UserEventTestService.prototype.watchAll = function (offset, size, sortBy, sortDirection, filter, options) {
31346
+ return rxjs.of({ data: this.userEvents });
31347
+ };
31348
+ return UserEventTestService;
31349
+ }(AbstractUserEventService));
31350
+ UserEventTestService.decorators = [
31351
+ { type: i0.Injectable }
31352
+ ];
31353
+ UserEventTestService.ctorParameters = function () { return [
31354
+ { type: GraphqlService },
31355
+ { type: AccountService },
31356
+ { type: NetworkService },
31357
+ { type: i1$2.TranslateService },
31358
+ { type: Environment, decorators: [{ type: i0.Optional }, { type: i0.Inject, args: [ENVIRONMENT,] }] }
31359
+ ]; };
31360
+
31067
31361
  var UserEventModule = /** @class */ (function () {
31068
31362
  function UserEventModule() {
31069
31363
  }
@@ -31084,6 +31378,9 @@
31084
31378
  exports: [
31085
31379
  UserEventsTable,
31086
31380
  UserEventNotificationComponent
31381
+ ],
31382
+ providers: [
31383
+ { provide: UserEventServiceToken, useClass: UserEventTestService }
31087
31384
  ]
31088
31385
  },] }
31089
31386
  ];
@@ -31353,11 +31650,14 @@
31353
31650
  // @dynamic
31354
31651
  exports.JobProgression = JobProgression_1 = /** @class */ (function (_super) {
31355
31652
  __extends(JobProgression, _super);
31356
- function JobProgression() {
31357
- return _super.call(this, JobProgression_1.TYPENAME) || this;
31653
+ function JobProgression(id) {
31654
+ var _this = _super.call(this, JobProgression_1.TYPENAME) || this;
31655
+ _this.id = id;
31656
+ return _this;
31358
31657
  }
31359
31658
  JobProgression.prototype.fromObject = function (source) {
31360
31659
  _super.prototype.fromObject.call(this, source);
31660
+ this.name = source.name;
31361
31661
  this.message = source.message;
31362
31662
  this.current = source.current;
31363
31663
  this.total = source.total;
@@ -31369,7 +31669,7 @@
31369
31669
  ], exports.JobProgression);
31370
31670
 
31371
31671
  var JobProgressionServiceToken = new i0.InjectionToken('JobProgressionService');
31372
- var jobProgressionSubscription = core.gql(templateObject_1$4 || (templateObject_1$4 = __makeTemplateObject(["subscription UpdateJobProgression($id: Int!, $interval: Int){\n data: updateJobProgression(id: $id, interval: $interval) {\n id\n message\n current\n total\n updateDate\n }\n}"], ["subscription UpdateJobProgression($id: Int!, $interval: Int){\n data: updateJobProgression(id: $id, interval: $interval) {\n id\n message\n current\n total\n updateDate\n }\n}"])));
31672
+ var jobProgressionSubscription = core.gql(templateObject_1$4 || (templateObject_1$4 = __makeTemplateObject(["subscription UpdateJobProgression($id: Int!, $interval: Int){\n data: updateJobProgression(id: $id, interval: $interval) {\n id\n name\n message\n current\n total\n }\n}"], ["subscription UpdateJobProgression($id: Int!, $interval: Int){\n data: updateJobProgression(id: $id, interval: $interval) {\n id\n name\n message\n current\n total\n }\n}"])));
31373
31673
  var JobProgressionService = /** @class */ (function (_super) {
31374
31674
  __extends(JobProgressionService, _super);
31375
31675
  function JobProgressionService(graphql, environment) {
@@ -31421,8 +31721,8 @@
31421
31721
  JobProgressionList.decorators = [
31422
31722
  { type: i0.Component, args: [{
31423
31723
  selector: 'app-job-progression-list',
31424
- template: "<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!jobProgressions?.length\">\n {{'SOCIAL.JOB.PROGRESSION.EMPTY' | translate}}\n </ion-item>\n <ion-item *ngFor=\"let jobProgression of jobProgressions\">\n <ion-grid class=\"ion-no-margin\">\n <ion-row>\n <ion-col>\n {{jobProgression.message}}\n </ion-col>\n </ion-row>\n <ion-row>\n <ion-col>\n <ion-progress-bar\n [value]=\"jobProgression.total > 0 ? jobProgression.current / jobProgression.total : undefined\"\n [type]=\"jobProgression.total > 0 ? 'determinate' : 'indeterminate'\">\n </ion-progress-bar>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
31425
- styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}"]
31724
+ template: "<ion-list class=\"ion-list-popover\">\n\n <ion-row class=\"ion-list-header column\">\n <ion-col>\n <ion-label>{{titleI18n | translate}}</ion-label>\n </ion-col>\n </ion-row>\n\n <ion-item *ngIf=\"!jobProgressions?.length\">\n {{'SOCIAL.JOB.PROGRESSION.EMPTY' | translate}}\n </ion-item>\n <ion-item *ngFor=\"let jobProgression of jobProgressions\" class=\"ion-item-job-progression\">\n <ion-grid class=\"ion-no-margin\">\n <ion-row class=\"name\">\n <ion-col>\n {{jobProgression.name}}\n </ion-col>\n </ion-row>\n <ion-row class=\"message\">\n <ion-col>\n {{jobProgression.message}}\n </ion-col>\n </ion-row>\n <ion-row class=\"progress-bar\">\n <ion-col>\n <ion-progress-bar\n [value]=\"jobProgression.total > 0 ? jobProgression.current / jobProgression.total : undefined\"\n [type]=\"jobProgression.total > 0 ? 'determinate' : 'indeterminate'\">\n </ion-progress-bar>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n\n</ion-list>\n",
31725
+ styles: [":host(.popover-viewport){overflow-y:auto;-webkit-user-select:none;-moz-user-select:none;user-select:none}.ion-item-job-progression{font-size:.9em}.ion-item-job-progression .message{font-style:italic}.ion-item-job-progression .progress-bar{margin-top:5px;margin-bottom:5px}"]
31426
31726
  },] }
31427
31727
  ];
31428
31728
  JobProgressionList.ctorParameters = function () { return []; };
@@ -31466,13 +31766,16 @@
31466
31766
  console.warn(this._logPrefix + "No service injected. Can't add a job");
31467
31767
  return;
31468
31768
  }
31469
- if (this.debug) {
31470
- console.debug(this._logPrefix + "Add job id=" + id);
31471
- }
31472
31769
  if (!!this.getProgression(id)) {
31473
31770
  console.warn(this._logPrefix + "Job (id=" + id + ") already present");
31474
31771
  return;
31475
31772
  }
31773
+ if (this.debug) {
31774
+ console.debug(this._logPrefix + "Add job id=" + id);
31775
+ }
31776
+ // Adding empty job progression
31777
+ var progression = new exports.JobProgression(id);
31778
+ this.jobProgressions.push(progression);
31476
31779
  this.disabled = false;
31477
31780
  var sub = this.jobProgressionService.listenChanges(id)
31478
31781
  .pipe(operators.filter(function (progression) {
@@ -31487,7 +31790,7 @@
31487
31790
  // Get current progression object
31488
31791
  var currentProgression = _this.getProgression(id);
31489
31792
  if (!currentProgression) {
31490
- // add it
31793
+ // add it if absent
31491
31794
  _this.jobProgressions.push(progression);
31492
31795
  if (_this.debug) {
31493
31796
  console.debug(_this._logPrefix + "Progression added id=" + id, progression);
@@ -34246,12 +34549,13 @@
34246
34549
  exports.ɵi = AppUpdateOfflineModeCard;
34247
34550
  exports.ɵj = AppIconComponent;
34248
34551
  exports.ɵk = UserEventNotificationList;
34249
- exports.ɵl = JobProgressionList;
34250
- exports.ɵm = DateTestPage;
34251
- exports.ɵn = NumpadTestPage;
34252
- exports.ɵo = MatBadgeIconTestPage;
34253
- exports.ɵp = ToastTestingModule;
34254
- exports.ɵq = ToastTestingPage;
34552
+ exports.ɵl = UserEventTestService;
34553
+ exports.ɵm = JobProgressionList;
34554
+ exports.ɵn = DateTestPage;
34555
+ exports.ɵo = NumpadTestPage;
34556
+ exports.ɵp = MatBadgeIconTestPage;
34557
+ exports.ɵq = ToastTestingModule;
34558
+ exports.ɵr = ToastTestingPage;
34255
34559
 
34256
34560
  Object.defineProperty(exports, '__esModule', { value: true });
34257
34561