@yuuvis/client-framework 3.1.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/fesm2022/yuuvis-client-framework-actions.mjs +209 -126
  2. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -1
  3. package/fesm2022/yuuvis-client-framework-app-bar.mjs +3 -3
  4. package/fesm2022/yuuvis-client-framework-app-bar.mjs.map +1 -1
  5. package/fesm2022/yuuvis-client-framework-badges.mjs +379 -0
  6. package/fesm2022/yuuvis-client-framework-badges.mjs.map +1 -0
  7. package/fesm2022/yuuvis-client-framework-breadcrumb.mjs +3 -3
  8. package/fesm2022/yuuvis-client-framework-breadcrumb.mjs.map +1 -1
  9. package/fesm2022/yuuvis-client-framework-clipboard.mjs +8 -8
  10. package/fesm2022/yuuvis-client-framework-clipboard.mjs.map +1 -1
  11. package/fesm2022/yuuvis-client-framework-datepicker.mjs +31 -31
  12. package/fesm2022/yuuvis-client-framework-datepicker.mjs.map +1 -1
  13. package/fesm2022/yuuvis-client-framework-forms.mjs +65 -66
  14. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  15. package/fesm2022/yuuvis-client-framework-icons.mjs +9 -9
  16. package/fesm2022/yuuvis-client-framework-icons.mjs.map +1 -1
  17. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs +7 -7
  18. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs.map +1 -1
  19. package/fesm2022/yuuvis-client-framework-metadata-form.mjs +15 -15
  20. package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
  21. package/fesm2022/yuuvis-client-framework-object-details.mjs +53 -46
  22. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
  23. package/fesm2022/yuuvis-client-framework-object-flavor.mjs +18 -18
  24. package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -1
  25. package/fesm2022/yuuvis-client-framework-object-form.mjs +32 -32
  26. package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
  27. package/fesm2022/yuuvis-client-framework-object-preview.mjs +9 -9
  28. package/fesm2022/yuuvis-client-framework-object-preview.mjs.map +1 -1
  29. package/fesm2022/yuuvis-client-framework-object-relationship.mjs +28 -28
  30. package/fesm2022/yuuvis-client-framework-object-relationship.mjs.map +1 -1
  31. package/fesm2022/yuuvis-client-framework-object-summary.mjs +14 -14
  32. package/fesm2022/yuuvis-client-framework-object-summary.mjs.map +1 -1
  33. package/fesm2022/yuuvis-client-framework-object-versions.mjs +18 -12
  34. package/fesm2022/yuuvis-client-framework-object-versions.mjs.map +1 -1
  35. package/fesm2022/yuuvis-client-framework-pagination.mjs +3 -3
  36. package/fesm2022/yuuvis-client-framework-pagination.mjs.map +1 -1
  37. package/fesm2022/yuuvis-client-framework-query-list.mjs +7 -7
  38. package/fesm2022/yuuvis-client-framework-query-list.mjs.map +1 -1
  39. package/fesm2022/yuuvis-client-framework-renderer.mjs +39 -39
  40. package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
  41. package/fesm2022/yuuvis-client-framework-sequence-list.mjs +3 -3
  42. package/fesm2022/yuuvis-client-framework-sequence-list.mjs.map +1 -1
  43. package/fesm2022/yuuvis-client-framework-simple-search.mjs +3 -3
  44. package/fesm2022/yuuvis-client-framework-simple-search.mjs.map +1 -1
  45. package/fesm2022/yuuvis-client-framework-sort.mjs +3 -3
  46. package/fesm2022/yuuvis-client-framework-sort.mjs.map +1 -1
  47. package/fesm2022/yuuvis-client-framework-tile-list.mjs +163 -125
  48. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  49. package/fesm2022/yuuvis-client-framework-token-search.mjs +7 -7
  50. package/fesm2022/yuuvis-client-framework-token-search.mjs.map +1 -1
  51. package/fesm2022/yuuvis-client-framework-tree.mjs +9 -9
  52. package/fesm2022/yuuvis-client-framework-tree.mjs.map +1 -1
  53. package/fesm2022/yuuvis-client-framework-upload-progress.mjs +10 -10
  54. package/fesm2022/yuuvis-client-framework-upload-progress.mjs.map +1 -1
  55. package/fesm2022/yuuvis-client-framework.mjs +96 -51
  56. package/fesm2022/yuuvis-client-framework.mjs.map +1 -1
  57. package/lib/assets/i18n/de.json +12 -1
  58. package/lib/assets/i18n/en.json +12 -1
  59. package/package.json +9 -5
  60. package/types/yuuvis-client-framework-actions.d.ts +81 -52
  61. package/types/yuuvis-client-framework-badges.d.ts +194 -0
  62. package/types/yuuvis-client-framework-object-details.d.ts +5 -5
  63. package/types/yuuvis-client-framework-object-versions.d.ts +1 -0
  64. package/types/yuuvis-client-framework-tile-list.d.ts +10 -6
  65. package/types/yuuvis-client-framework.d.ts +13 -0
@@ -1 +1 @@
1
- {"version":3,"file":"yuuvis-client-framework-upload-progress.mjs","sources":["../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.ts","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.html","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress.component.ts","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress.component.html","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress.module.ts","../../../../../libs/yuuvis/client-framework/upload-progress/src/yuuvis-client-framework-upload-progress.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, computed, inject, input, output } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatProgressSpinner } from '@angular/material/progress-spinner';\nimport { ProgressStatusItem, TranslateService, UploadResult, UploadService } from '@yuuvis/client-core';\n\n@Component({\n selector: 'yuv-upload-progress-overlay',\n standalone: true,\n imports: [CommonModule, MatButtonModule, MatIconModule, MatProgressSpinner],\n templateUrl: './upload-progress-overlay.component.html',\n styleUrl: './upload-progress-overlay.component.scss'\n})\nexport class UploadProgressOverlayComponent {\n #uploadService = inject(UploadService);\n translate = inject(TranslateService);\n\n items = input<ProgressStatusItem[]>();\n _items = computed(() => {\n const items = this.items() || [];\n items.forEach((item) => {\n if (item.err) {\n item.err.message = this.#getErrorMessage(item.err.code);\n }\n });\n return items;\n });\n itemClick = output<UploadResult>();\n\n remove(id?: string) {\n this.#uploadService.cancelItem(id);\n }\n\n #getErrorMessage(status: number): string {\n switch (status) {\n case 403:\n return this.translate.instant('yuv.upload-progress-overlay.error.403');\n default:\n return this.translate.instant('yuv.upload-progress-overlay.error.default');\n }\n }\n}\n","<ul>\n @for (item of _items(); track item.id) {\n @let progress = item.progress | async;\n <li [ngClass]=\"{ err: !!item.err, done: !!item.result }\" [style.--progress]=\"progress + '%'\">\n <button mat-icon-button class=\"remove\" (click)=\"remove(item.id)\">\n <mat-icon [ngClass]=\"{ err: !!item.err }\">close</mat-icon>\n </button>\n\n @if (!item.result) {\n <div class=\"name\">{{ item.filename }}\n @if(item.err) {\n <span class=\"error\">{{item.err.message}}</span>\n }\n </div>\n <div class=\"progress\">\n @if (progress && progress < 100) {\n <div class=\"percentage\">{{ progress }}</div>\n }\n @else if(item.err) {\n <mat-icon class=\"error\">warning</mat-icon>\n }\n @else {\n <mat-progress-spinner mode=\"indeterminate\" class=\"ymt-progress-spinner--tiny\"></mat-progress-spinner>\n }\n </div>\n } @else {\n <div class=\"result-items\">\n @for (res of item.result; track $index) {\n <div class=\"result-item\">\n <div class=\"name\" (click)=\"itemClick.emit(res)\">\n {{ res.label }}\n </div>\n </div>\n }\n </div>\n <mat-icon class=\"done\">check</mat-icon>\n }\n </li>\n }\n</ul>\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { TranslatePipe, UploadResult, UploadService } from '@yuuvis/client-core';\nimport { UploadProgressOverlayComponent } from './upload-progress-overlay/upload-progress-overlay.component';\n\n@Component({\n selector: 'yuv-upload-progress',\n standalone: true,\n imports: [CommonModule, MatButtonModule, MatIconModule, TranslatePipe, UploadProgressOverlayComponent],\n templateUrl: './upload-progress.component.html',\n styleUrl: './upload-progress.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.expanded]': 'expanded'\n }\n})\nexport class UploadProgressComponent {\n //#region Dependencies\n\n #uploadService = inject(UploadService);\n\n //#endregion\n\n //#region Angular stuff\n\n expanded = true;\n resultItemClick = output<UploadResult>();\n\n /**\n * Optional list of scope identifiers this component instance should respond to.\n *\n * When provided, the component will display upload progress only for uploads\n * that were initiated with a matching scope via `UploadService.uploadFile()` or\n * `UploadService.multipartUpload()`. This allows multiple `UploadProgressComponent`\n * instances to coexist in different sections of the UI, each showing only the uploads\n * relevant to its own context.\n *\n * If omitted, the component responds to all uploads regardless of scope.\n *\n * @example\n * ```html\n * <!-- Shows only uploads tagged with scope 'mail-editor' or 'attachments-panel' -->\n * <yuv-upload-progress [scopes]=\"['mail-editor', 'attachments-panel']\" />\n *\n * <!-- Shows all uploads (no scope filter) -->\n * <yuv-upload-progress />\n * ```\n */\n scopes = input<string[]>();\n //#endregion\n\n //#region Properties\n\n completedUp$ = this.#uploadService.uploadStatus$;\n\n #status = toSignal(this.#uploadService.status$);\n\n filteredItems = computed(() => {\n const items = this.#status()?.items ?? [];\n const scopes = this.scopes();\n return scopes?.length ? items.filter((item) => item.scope && scopes.includes(item.scope)) : items;\n });\n\n //#endregion\n\n //#region UI Methods\n\n close(): void {\n this.filteredItems().forEach((item) => this.#uploadService.cancelItem(item.id));\n }\n\n //#endregion\n}\n","@let items = filteredItems();\n@if (items.length) {\n @let completed = completedUp$ | async;\n\n <div class=\"upload-progress\">\n <header>\n <h4>\n @if (!completed) {\n {{ 'yuv.upload-progress.header.uploading' | translate: { count: items.length } }}\n } @else {\n {{ 'yuv.upload-progress.header.uploaded' | translate: { count: items.length } }}\n }\n </h4>\n <button mat-icon-button (click)=\"expanded = !expanded\">\n <mat-icon class=\"toggle\">keyboard_arrow_down</mat-icon>\n </button>\n <button mat-icon-button (click)=\"close()\">\n <mat-icon class=\"toggle\">clear</mat-icon>\n </button>\n </header>\n @if (expanded) {\n <yuv-upload-progress-overlay [items]=\"items\" (itemClick)=\"resultItemClick.emit($event)\" />\n }\n </div>\n}\n","import { NgModule } from \"@angular/core\";\nimport { UploadProgressComponent } from \"./upload-progress.component\";\n\n\nconst cmp = [\n UploadProgressComponent\n]\n\n@NgModule({\n imports: [cmp],\n exports: [cmp]\n })\n export class YuvUploadProgressModule {}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2","i3"],"mappings":"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"}
1
+ {"version":3,"file":"yuuvis-client-framework-upload-progress.mjs","sources":["../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.ts","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.html","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress.component.ts","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress.component.html","../../../../../libs/yuuvis/client-framework/upload-progress/src/lib/upload-progress/upload-progress.module.ts","../../../../../libs/yuuvis/client-framework/upload-progress/src/yuuvis-client-framework-upload-progress.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport { Component, computed, inject, input, output } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatProgressSpinner } from '@angular/material/progress-spinner';\nimport { ProgressStatusItem, TranslateService, UploadResult, UploadService } from '@yuuvis/client-core';\n\n@Component({\n selector: 'yuv-upload-progress-overlay',\n standalone: true,\n imports: [CommonModule, MatButtonModule, MatIconModule, MatProgressSpinner],\n templateUrl: './upload-progress-overlay.component.html',\n styleUrl: './upload-progress-overlay.component.scss'\n})\nexport class UploadProgressOverlayComponent {\n #uploadService = inject(UploadService);\n translate = inject(TranslateService);\n\n items = input<ProgressStatusItem[]>();\n _items = computed(() => {\n const items = this.items() || [];\n items.forEach((item) => {\n if (item.err) {\n item.err.message = this.#getErrorMessage(item.err.code);\n }\n });\n return items;\n });\n itemClick = output<UploadResult>();\n\n remove(id?: string) {\n this.#uploadService.cancelItem(id);\n }\n\n #getErrorMessage(status: number): string {\n switch (status) {\n case 403:\n return this.translate.instant('yuv.upload-progress-overlay.error.403');\n default:\n return this.translate.instant('yuv.upload-progress-overlay.error.default');\n }\n }\n}\n","<ul>\n @for (item of _items(); track item.id) {\n @let progress = item.progress | async;\n <li [ngClass]=\"{ err: !!item.err, done: !!item.result }\" [style.--progress]=\"progress + '%'\">\n <button mat-icon-button class=\"remove\" (click)=\"remove(item.id)\">\n <mat-icon [ngClass]=\"{ err: !!item.err }\">close</mat-icon>\n </button>\n\n @if (!item.result) {\n <div class=\"name\">{{ item.filename }}\n @if(item.err) {\n <span class=\"error\">{{item.err.message}}</span>\n }\n </div>\n <div class=\"progress\">\n @if (progress && progress < 100) {\n <div class=\"percentage\">{{ progress }}</div>\n }\n @else if(item.err) {\n <mat-icon class=\"error\">warning</mat-icon>\n }\n @else {\n <mat-progress-spinner mode=\"indeterminate\" class=\"ymt-progress-spinner--tiny\"></mat-progress-spinner>\n }\n </div>\n } @else {\n <div class=\"result-items\">\n @for (res of item.result; track $index) {\n <div class=\"result-item\">\n <div class=\"name\" (click)=\"itemClick.emit(res)\">\n {{ res.label }}\n </div>\n </div>\n }\n </div>\n <mat-icon class=\"done\">check</mat-icon>\n }\n </li>\n }\n</ul>\n","import { CommonModule } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { TranslatePipe, UploadResult, UploadService } from '@yuuvis/client-core';\nimport { UploadProgressOverlayComponent } from './upload-progress-overlay/upload-progress-overlay.component';\n\n@Component({\n selector: 'yuv-upload-progress',\n standalone: true,\n imports: [CommonModule, MatButtonModule, MatIconModule, TranslatePipe, UploadProgressOverlayComponent],\n templateUrl: './upload-progress.component.html',\n styleUrl: './upload-progress.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class.expanded]': 'expanded'\n }\n})\nexport class UploadProgressComponent {\n //#region Dependencies\n\n #uploadService = inject(UploadService);\n\n //#endregion\n\n //#region Angular stuff\n\n expanded = true;\n resultItemClick = output<UploadResult>();\n\n /**\n * Optional list of scope identifiers this component instance should respond to.\n *\n * When provided, the component will display upload progress only for uploads\n * that were initiated with a matching scope via `UploadService.uploadFile()` or\n * `UploadService.multipartUpload()`. This allows multiple `UploadProgressComponent`\n * instances to coexist in different sections of the UI, each showing only the uploads\n * relevant to its own context.\n *\n * If omitted, the component responds to all uploads regardless of scope.\n *\n * @example\n * ```html\n * <!-- Shows only uploads tagged with scope 'mail-editor' or 'attachments-panel' -->\n * <yuv-upload-progress [scopes]=\"['mail-editor', 'attachments-panel']\" />\n *\n * <!-- Shows all uploads (no scope filter) -->\n * <yuv-upload-progress />\n * ```\n */\n scopes = input<string[]>();\n //#endregion\n\n //#region Properties\n\n completedUp$ = this.#uploadService.uploadStatus$;\n\n #status = toSignal(this.#uploadService.status$);\n\n filteredItems = computed(() => {\n const items = this.#status()?.items ?? [];\n const scopes = this.scopes();\n return scopes?.length ? items.filter((item) => item.scope && scopes.includes(item.scope)) : items;\n });\n\n //#endregion\n\n //#region UI Methods\n\n close(): void {\n this.filteredItems().forEach((item) => this.#uploadService.cancelItem(item.id));\n }\n\n //#endregion\n}\n","@let items = filteredItems();\n@if (items.length) {\n @let completed = completedUp$ | async;\n\n <div class=\"upload-progress\">\n <header>\n <h4>\n @if (!completed) {\n {{ 'yuv.upload-progress.header.uploading' | translate: { count: items.length } }}\n } @else {\n {{ 'yuv.upload-progress.header.uploaded' | translate: { count: items.length } }}\n }\n </h4>\n <button mat-icon-button (click)=\"expanded = !expanded\">\n <mat-icon class=\"toggle\">keyboard_arrow_down</mat-icon>\n </button>\n <button mat-icon-button (click)=\"close()\">\n <mat-icon class=\"toggle\">clear</mat-icon>\n </button>\n </header>\n @if (expanded) {\n <yuv-upload-progress-overlay [items]=\"items\" (itemClick)=\"resultItemClick.emit($event)\" />\n }\n </div>\n}\n","import { NgModule } from \"@angular/core\";\nimport { UploadProgressComponent } from \"./upload-progress.component\";\n\n\nconst cmp = [\n UploadProgressComponent\n]\n\n@NgModule({\n imports: [cmp],\n exports: [cmp]\n })\n export class YuvUploadProgressModule {}","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["i1","i2","i3"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, Injectable, signal, ChangeDetectionStrategy, Component, makeEnvironmentProviders, provideAppInitializer, NgZone, NgModule } from '@angular/core';
2
+ import { inject, Injectable, signal, ChangeDetectionStrategy, Component, DestroyRef, makeEnvironmentProviders, provideAppInitializer, NgZone, NgModule } from '@angular/core';
3
+ import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
3
4
  import { TranslateService } from '@ngx-translate/core';
4
- import { AppCacheService, BackendService, UserService } from '@yuuvis/client-core';
5
+ import { AppCacheService, BackendService, UserService, EventService, YuvEventType } from '@yuuvis/client-core';
5
6
  import { finalize, timer, switchMap, map, debounceTime } from 'rxjs';
6
- import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
7
7
  import * as i1 from '@angular/material/button';
8
8
  import { MatButtonModule } from '@angular/material/button';
9
9
  import { MatSnackBar, MatSnackBarRef, MAT_SNACK_BAR_DATA, MatSnackBarLabel, MatSnackBarActions, MatSnackBarAction } from '@angular/material/snack-bar';
@@ -509,10 +509,10 @@ class HaloFocusService {
509
509
  this.#stopTracking();
510
510
  }
511
511
  };
512
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HaloFocusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
513
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HaloFocusService, providedIn: 'root' }); }
512
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: HaloFocusService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
513
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: HaloFocusService, providedIn: 'root' }); }
514
514
  }
515
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HaloFocusService, decorators: [{
515
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: HaloFocusService, decorators: [{
516
516
  type: Injectable,
517
517
  args: [{
518
518
  providedIn: 'root'
@@ -941,10 +941,10 @@ class HaloUtilityService {
941
941
  haloElement.style.height = `${height}px`;
942
942
  haloElement.style.borderRadius = cs.borderRadius || '8px';
943
943
  }
944
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HaloUtilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
945
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HaloUtilityService }); }
944
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: HaloUtilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
945
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: HaloUtilityService }); }
946
946
  }
947
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: HaloUtilityService, decorators: [{
947
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: HaloUtilityService, decorators: [{
948
948
  type: Injectable
949
949
  }] });
950
950
 
@@ -997,10 +997,10 @@ class SnackBarService {
997
997
  panelClass: ['yuv-snack-bar', 'level-' + options.level]
998
998
  });
999
999
  }
1000
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SnackBarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1001
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SnackBarService, providedIn: 'root' }); }
1000
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SnackBarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1001
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SnackBarService, providedIn: 'root' }); }
1002
1002
  }
1003
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SnackBarService, decorators: [{
1003
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SnackBarService, decorators: [{
1004
1004
  type: Injectable,
1005
1005
  args: [{
1006
1006
  providedIn: 'root'
@@ -1026,8 +1026,8 @@ class SnackBarComponent {
1026
1026
  this.#snackBarRef.dismiss();
1027
1027
  }
1028
1028
  }
1029
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SnackBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1030
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SnackBarComponent, isStandalone: true, selector: "yuv-snack-bar-component", host: { properties: { "class.info": "level() === 'info'", "class.success": "level() === 'success'", "class.warning": "level() === 'warning'", "class.danger": "level() === 'danger'" } }, ngImport: i0, template: `
1029
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SnackBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1030
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: SnackBarComponent, isStandalone: true, selector: "yuv-snack-bar-component", host: { properties: { "class.info": "level() === 'info'", "class.success": "level() === 'success'", "class.warning": "level() === 'warning'", "class.danger": "level() === 'danger'" } }, ngImport: i0, template: `
1031
1031
  @let a = action();
1032
1032
  <span
1033
1033
  matSnackBarLabel
@@ -1046,7 +1046,7 @@ class SnackBarComponent {
1046
1046
  }
1047
1047
  `, isInline: true, styles: [":host{display:flex}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatSnackBarLabel, selector: "[matSnackBarLabel]" }, { kind: "directive", type: MatSnackBarActions, selector: "[matSnackBarActions]" }, { kind: "directive", type: MatSnackBarAction, selector: "[matSnackBarAction]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
1048
1048
  }
1049
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SnackBarComponent, decorators: [{
1049
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SnackBarComponent, decorators: [{
1050
1050
  type: Component,
1051
1051
  args: [{ selector: 'yuv-snack-bar-component', template: `
1052
1052
  @let a = action();
@@ -1156,6 +1156,8 @@ class SessionService {
1156
1156
  this.#snackBarService = inject(SnackBarService);
1157
1157
  this.#backendService = inject(BackendService);
1158
1158
  this.#userService = inject(UserService);
1159
+ this.#eventService = inject(EventService);
1160
+ this.#destroyRef = inject(DestroyRef);
1159
1161
  this.translate = inject(TranslateService);
1160
1162
  //#endregion
1161
1163
  //#region Properties
@@ -1167,6 +1169,7 @@ class SessionService {
1167
1169
  this.#trackingWindowActivity = false;
1168
1170
  this.#userActivityTrackingInitialized = false;
1169
1171
  this.#extendingSessionViaBackend = false;
1172
+ this.#isLoggingOut = false;
1170
1173
  this.#sessionChannel = new BroadcastChannel('session_channel');
1171
1174
  }
1172
1175
  //#region Dependencies
@@ -1188,12 +1191,15 @@ class SessionService {
1188
1191
  #snackBarService;
1189
1192
  #backendService;
1190
1193
  #userService;
1194
+ #eventService;
1195
+ #destroyRef;
1191
1196
  //#endregion
1192
1197
  //#region Properties
1193
1198
  #sessionDuration;
1194
1199
  #sessionStorageKey;
1195
1200
  #activityWindowBeforeEnd;
1196
1201
  #popupBeforeEnd;
1202
+ #activityWindowSchedule$;
1197
1203
  #activityWindowStart$;
1198
1204
  #activityWindowEnd$;
1199
1205
  #logoutTimer$;
@@ -1202,6 +1208,7 @@ class SessionService {
1202
1208
  #trackingWindowActivity;
1203
1209
  #userActivityTrackingInitialized;
1204
1210
  #extendingSessionViaBackend;
1211
+ #isLoggingOut;
1205
1212
  #sessionChannel;
1206
1213
  #snackReference;
1207
1214
  //#endregion
@@ -1221,6 +1228,7 @@ class SessionService {
1221
1228
  init(sessionDuration) {
1222
1229
  this.startSession(sessionDuration ?? sessionDefaultDuration);
1223
1230
  this.listenToChannel();
1231
+ this.listenToGlobalLogout();
1224
1232
  this.setupHttpDebounce();
1225
1233
  this.setupUserActivityTracking();
1226
1234
  }
@@ -1257,35 +1265,43 @@ class SessionService {
1257
1265
  * @param skipBackendCall When true, skips the whoami backend call (used when already triggered by HTTP activity)
1258
1266
  */
1259
1267
  extendSession(broadcast = true, expiresAt, skipBackendCall = false) {
1268
+ if (this.#isLoggingOut)
1269
+ return;
1260
1270
  const newExpiresAt = expiresAt ?? Date.now() + this.#sessionDuration;
1261
1271
  this.setExpiresAt(newExpiresAt);
1262
1272
  this.resetAllTimers();
1263
- if (!skipBackendCall && !this.#extendingSessionViaBackend) {
1264
- this.#extendingSessionViaBackend = true;
1265
- this.#backendService
1266
- .get('/idm/whoami')
1267
- .pipe(finalize(() => {
1268
- // Keep flag true longer than debounce time to prevent duplicate broadcasts
1269
- // from httpCommunicationOccurred$ triggered by this whoami call
1270
- setTimeout(() => {
1271
- this.#extendingSessionViaBackend = false;
1272
- // eslint-disable-next-line @typescript-eslint/no-magic-numbers
1273
- }, 600);
1274
- if (broadcast) {
1275
- this.#sessionChannel.postMessage({
1276
- type: ChannelMessage.SessionExtended,
1277
- expiresAt: newExpiresAt
1278
- });
1279
- }
1280
- }))
1281
- .subscribe();
1282
- }
1283
- else if (broadcast) {
1284
- this.#sessionChannel.postMessage({
1285
- type: ChannelMessage.SessionExtended,
1286
- expiresAt: newExpiresAt
1287
- });
1273
+ if (skipBackendCall) {
1274
+ if (broadcast) {
1275
+ this.#sessionChannel.postMessage({
1276
+ type: ChannelMessage.SessionExtended,
1277
+ expiresAt: newExpiresAt
1278
+ });
1279
+ }
1280
+ return;
1288
1281
  }
1282
+ // The #extendingSessionViaBackend flag is intentionally NOT checked here:
1283
+ // user-initiated extends (popup click, user activity at window end) must always
1284
+ // touch the backend so its session matches the freshly bumped local expiresAt.
1285
+ // The flag's sole purpose is to filter the HTTP debounce subscriber so the
1286
+ // whoami response itself doesn't trigger a recursive extend.
1287
+ this.#extendingSessionViaBackend = true;
1288
+ this.#backendService
1289
+ .get('/idm/whoami')
1290
+ .pipe(finalize(() => {
1291
+ // Keep flag true longer than debounce time to suppress the debounce
1292
+ // emission caused by the whoami response itself.
1293
+ setTimeout(() => {
1294
+ this.#extendingSessionViaBackend = false;
1295
+ // eslint-disable-next-line @typescript-eslint/no-magic-numbers
1296
+ }, 600);
1297
+ if (broadcast) {
1298
+ this.#sessionChannel.postMessage({
1299
+ type: ChannelMessage.SessionExtended,
1300
+ expiresAt: newExpiresAt
1301
+ });
1302
+ }
1303
+ }))
1304
+ .subscribe();
1289
1305
  }
1290
1306
  //#endregion
1291
1307
  //#region Core Logic
@@ -1302,8 +1318,30 @@ class SessionService {
1302
1318
  }
1303
1319
  };
1304
1320
  }
1321
+ /**
1322
+ * Listens to the global LOGOUT event emitted by AuthService.
1323
+ *
1324
+ * Covers logout paths that bypass SessionService.performLogout — e.g.,
1325
+ * 401 caught by AuthInterceptor or any manual `AuthService.logout()` call.
1326
+ * Without this, other tabs would not receive a SessionLogout broadcast and
1327
+ * the HTTP activity subscription would briefly stay alive after auth dies.
1328
+ *
1329
+ * Note: UI buttons that call only `UserService.logout()` (e.g. sidebar-nav)
1330
+ * do not emit this event — for those, the system still converges via the
1331
+ * 401 interceptor or local expiry.
1332
+ */
1333
+ listenToGlobalLogout() {
1334
+ this.#eventService
1335
+ .on(YuvEventType.LOGOUT)
1336
+ .pipe(takeUntilDestroyed(this.#destroyRef))
1337
+ .subscribe(() => this.performLogout(true));
1338
+ }
1305
1339
  scheduleActivityWindow() {
1306
- this.getExpiresAt().subscribe((expiresAt) => {
1340
+ // Capture the outer subscription so clearTimers can cancel a pending
1341
+ // async getExpiresAt() resolution. Without this, two extendSession calls
1342
+ // in quick succession could leak the inner timers of the first call when
1343
+ // its getExpiresAt resolves after the second call's clearTimers has run.
1344
+ this.#activityWindowSchedule$ = this.getExpiresAt().subscribe((expiresAt) => {
1307
1345
  const activityWindowStartIn = expiresAt - Date.now() - this.#activityWindowBeforeEnd;
1308
1346
  const activityWindowEndIn = expiresAt - Date.now() - this.#popupBeforeEnd;
1309
1347
  this.#activityWindowStart$ = timer(Math.max(activityWindowStartIn, 0)).subscribe(() => {
@@ -1347,7 +1385,11 @@ class SessionService {
1347
1385
  });
1348
1386
  }
1349
1387
  performLogout(broadcast = true) {
1388
+ if (this.#isLoggingOut)
1389
+ return;
1390
+ this.#isLoggingOut = true;
1350
1391
  this.clearTimers();
1392
+ this.#httpActivitySubscription$?.unsubscribe();
1351
1393
  this.#snackReference?.dismiss();
1352
1394
  if (broadcast) {
1353
1395
  this.#sessionChannel.postMessage({
@@ -1371,11 +1413,14 @@ class SessionService {
1371
1413
  setupUserActivityTracking() {
1372
1414
  if (this.#userActivityTrackingInitialized)
1373
1415
  return;
1374
- ['mousemove', 'keydown', 'click', 'scroll'].forEach((event) => window.addEventListener(event, () => {
1416
+ const handler = () => {
1375
1417
  if (this.#trackingWindowActivity) {
1376
1418
  this.#activityDetectedInWindow = true;
1377
1419
  }
1378
- }));
1420
+ };
1421
+ const events = ['mousemove', 'keydown', 'click', 'scroll'];
1422
+ events.forEach((event) => window.addEventListener(event, handler, { passive: true }));
1423
+ this.#destroyRef.onDestroy(() => events.forEach((event) => window.removeEventListener(event, handler)));
1379
1424
  this.#userActivityTrackingInitialized = true;
1380
1425
  }
1381
1426
  //#endregion
@@ -1392,15 +1437,15 @@ class SessionService {
1392
1437
  this.#appCacheService.setItem(this.#sessionStorageKey, expiresAt).subscribe();
1393
1438
  }
1394
1439
  clearTimers() {
1440
+ this.#activityWindowSchedule$?.unsubscribe();
1395
1441
  this.#activityWindowStart$?.unsubscribe();
1396
1442
  this.#activityWindowEnd$?.unsubscribe();
1397
1443
  this.#logoutTimer$?.unsubscribe();
1398
- this.#httpActivitySubscription$?.unsubscribe();
1399
1444
  }
1400
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1401
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SessionService, providedIn: 'root' }); }
1445
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SessionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1446
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SessionService, providedIn: 'root' }); }
1402
1447
  }
1403
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SessionService, decorators: [{
1448
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SessionService, decorators: [{
1404
1449
  type: Injectable,
1405
1450
  args: [{ providedIn: 'root' }]
1406
1451
  }] });
@@ -1526,11 +1571,11 @@ function provideSession(sessionDuration) {
1526
1571
  }
1527
1572
 
1528
1573
  class YuuvisClientFrameworkModule {
1529
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: YuuvisClientFrameworkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1530
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: YuuvisClientFrameworkModule, imports: [CommonModule] }); }
1531
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: YuuvisClientFrameworkModule, imports: [CommonModule] }); }
1574
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuuvisClientFrameworkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1575
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: YuuvisClientFrameworkModule, imports: [CommonModule] }); }
1576
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuuvisClientFrameworkModule, imports: [CommonModule] }); }
1532
1577
  }
1533
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: YuuvisClientFrameworkModule, decorators: [{
1578
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: YuuvisClientFrameworkModule, decorators: [{
1534
1579
  type: NgModule,
1535
1580
  args: [{
1536
1581
  imports: [CommonModule],