@acorex/platform 20.9.30 → 20.9.32

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.
@@ -16,7 +16,7 @@ import { AXPLayoutRendererComponent, AXPLayoutBuilderService } from '@acorex/pla
16
16
  import * as i1 from '@angular/common';
17
17
  import { CommonModule, NgTemplateOutlet, AsyncPipe, isPlatformBrowser } from '@angular/common';
18
18
  import * as i0 from '@angular/core';
19
- import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, signal, effect, computed, InjectionToken, Injectable, Directive, viewChild, contentChild, ElementRef, output, afterNextRender, model, EventEmitter, forwardRef, ViewChild, Output, Input, untracked, DestroyRef, PLATFORM_ID, linkedSignal, ViewChildren, TemplateRef, contentChildren } from '@angular/core';
19
+ import { input, ChangeDetectionStrategy, ViewEncapsulation, Component, inject, signal, effect, linkedSignal, computed, InjectionToken, Injectable, Directive, viewChild, contentChild, ElementRef, output, afterNextRender, model, EventEmitter, forwardRef, ViewChild, Output, Input, untracked, DestroyRef, PLATFORM_ID, ViewChildren, TemplateRef, contentChildren } from '@angular/core';
20
20
  import { AXAccordionCdkModule } from '@acorex/cdk/accordion';
21
21
  import { AXTagModule } from '@acorex/components/tag';
22
22
  import * as i1$1 from '@acorex/components/avatar';
@@ -70,7 +70,7 @@ import { AXCalendarService } from '@acorex/core/date-time';
70
70
  import { AXPFilterOperatorMiddlewareService, AXPSettingsService, ALL_DEFAULT_OPERATORS, AXPFileStorageService, withDefaultMultiLanguageOnWidgetProperty, AXPDefaultMultiLanguageConfigService, resolveSearchableText, AXP_PLATFORM_CONFIG_TOKEN } from '@acorex/platform/common';
71
71
  import { resolveEntityListFilterQueryField, resolveEntityListFilterContextField } from '@acorex/platform/layout/entity-contracts';
72
72
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
73
- import { Subject, filter, BehaviorSubject, timer, takeUntil } from 'rxjs';
73
+ import { Subject, filter, BehaviorSubject, timer } from 'rxjs';
74
74
  import * as i1$7 from '@acorex/components/image-editor';
75
75
  import { AXImageEditorContainerComponent, AXImageEditorModule } from '@acorex/components/image-editor';
76
76
  import * as i3$5 from '@acorex/components/toolbar';
@@ -286,11 +286,11 @@ class AXPAvatarComponent {
286
286
  this.fallbackText = input(undefined, ...(ngDevMode ? [{ debugName: "fallbackText" }] : /* istanbul ignore next */ []));
287
287
  /** Forces placeholder mode and '?' fallback. */
288
288
  this.placeholder = input(false, ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
289
- this.isAvatarLoaded = signal(false, ...(ngDevMode ? [{ debugName: "isAvatarLoaded" }] : /* istanbul ignore next */ []));
289
+ this.imageFailed = linkedSignal({ ...(ngDevMode ? { debugName: "imageFailed" } : /* istanbul ignore next */ {}), source: () => this.src(),
290
+ computation: () => false });
290
291
  this.normalizedName = computed(() => (this.fullName() ?? '').trim(), ...(ngDevMode ? [{ debugName: "normalizedName" }] : /* istanbul ignore next */ []));
291
292
  this.resolvedSrc = computed(() => (this.src() ?? '').trim(), ...(ngDevMode ? [{ debugName: "resolvedSrc" }] : /* istanbul ignore next */ []));
292
- this.hasAvatar = computed(() => !isNil(this.resolvedSrc()) && !isEmpty(this.resolvedSrc()) && !this.placeholder(), ...(ngDevMode ? [{ debugName: "hasAvatar" }] : /* istanbul ignore next */ []));
293
- this.isLoading = computed(() => this.hasAvatar() && !this.isAvatarLoaded(), ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
293
+ this.hasAvatar = computed(() => !isNil(this.resolvedSrc()) && !isEmpty(this.resolvedSrc()) && !this.placeholder() && !this.imageFailed(), ...(ngDevMode ? [{ debugName: "hasAvatar" }] : /* istanbul ignore next */ []));
294
294
  this.avatarText = computed(() => {
295
295
  if (this.placeholder()) {
296
296
  return '?';
@@ -305,10 +305,10 @@ class AXPAvatarComponent {
305
305
  this.title = computed(() => this.normalizedName(), ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
306
306
  }
307
307
  onImageError(event) {
308
- this.isAvatarLoaded.set(false);
308
+ this.imageFailed.set(true);
309
309
  }
310
310
  onImageLoad(event) {
311
- this.isAvatarLoaded.set(true);
311
+ this.imageFailed.set(false);
312
312
  }
313
313
  computeInitials(name) {
314
314
  if (!name) {
@@ -345,11 +345,11 @@ class AXPAvatarComponent {
345
345
  // ax-accent3-lightest
346
346
  }
347
347
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAvatarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
348
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPAvatarComponent, isStandalone: true, selector: "axp-avatar", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, fullName: { classPropertyName: "fullName", publicName: "fullName", isSignal: true, isRequired: false, transformFunction: null }, fallbackText: { classPropertyName: "fallbackText", publicName: "fallbackText", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ax-avatar [size]=\"size()\" class=\"ax-cursor-pointer ax-relative\" [title]=\"title()\"\n class=\"ax-{{ avatarColor() }}-lightest ax-border \">\n @if (hasAvatar()) {\n <ng-container>\n <ax-image (onError)=\"onImageError($event)\" (onLoad)=\"onImageLoad($event)\" [src]=\"resolvedSrc()\"\n [class.ax-opacity-0]=\"isLoading()\" class=\"ax-transition-opacity ax-duration-200\" />\n @if (isLoading()) {\n <ax-icon icon=\"fa-solid fa-user fa-2x\" class=\"ax-text-3xl\" />\n }\n </ng-container>\n } @else {\n <ax-text>\n <small class=\"ax-font-semibold\" [style.font-size]=\"size() * 0.35 + 'px'\">{{ avatarText() }}</small>\n </ax-text>\n }\n</ax-avatar>", styles: [":host ax-text{border-style:none;background-color:transparent;color:unset!important}\n"], dependencies: [{ kind: "ngmodule", type: AXAvatarModule }, { kind: "component", type: i1$1.AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXImageModule }, { kind: "component", type: i3$1.AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
348
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPAvatarComponent, isStandalone: true, selector: "axp-avatar", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, fullName: { classPropertyName: "fullName", publicName: "fullName", isSignal: true, isRequired: false, transformFunction: null }, fallbackText: { classPropertyName: "fallbackText", publicName: "fallbackText", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<ax-avatar [size]=\"size()\" class=\"ax-cursor-pointer ax-relative\" [title]=\"title()\"\n class=\"ax-{{ avatarColor() }}-lightest ax-border \">\n @if (hasAvatar()) {\n <ax-image\n (onError)=\"onImageError($event)\"\n (onLoad)=\"onImageLoad($event)\"\n [src]=\"resolvedSrc()\"\n />\n } @else {\n <ax-text>\n <small class=\"ax-font-semibold\" [style.font-size]=\"size() * 0.35 + 'px'\">{{ avatarText() }}</small>\n </ax-text>\n }\n</ax-avatar>\n", styles: [":host ax-text{border-style:none;background-color:transparent;color:unset!important}:host ax-image{position:absolute!important;inset:0;width:100%!important;height:100%!important}:host ax-image img{display:block!important}\n"], dependencies: [{ kind: "ngmodule", type: AXAvatarModule }, { kind: "component", type: i1$1.AXAvatarComponent, selector: "ax-avatar", inputs: ["color", "size", "shape", "look"], outputs: ["sizeChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXImageModule }, { kind: "component", type: i3$1.AXImageComponent, selector: "ax-image", inputs: ["width", "height", "overlayMode", "src", "alt", "priority", "lazy"], outputs: ["onLoad", "onError"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
349
349
  }
350
350
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAvatarComponent, decorators: [{
351
351
  type: Component,
352
- args: [{ selector: 'axp-avatar', imports: [AXAvatarModule, AXDecoratorModule, AXImageModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-avatar [size]=\"size()\" class=\"ax-cursor-pointer ax-relative\" [title]=\"title()\"\n class=\"ax-{{ avatarColor() }}-lightest ax-border \">\n @if (hasAvatar()) {\n <ng-container>\n <ax-image (onError)=\"onImageError($event)\" (onLoad)=\"onImageLoad($event)\" [src]=\"resolvedSrc()\"\n [class.ax-opacity-0]=\"isLoading()\" class=\"ax-transition-opacity ax-duration-200\" />\n @if (isLoading()) {\n <ax-icon icon=\"fa-solid fa-user fa-2x\" class=\"ax-text-3xl\" />\n }\n </ng-container>\n } @else {\n <ax-text>\n <small class=\"ax-font-semibold\" [style.font-size]=\"size() * 0.35 + 'px'\">{{ avatarText() }}</small>\n </ax-text>\n }\n</ax-avatar>", styles: [":host ax-text{border-style:none;background-color:transparent;color:unset!important}\n"] }]
352
+ args: [{ selector: 'axp-avatar', imports: [AXAvatarModule, AXDecoratorModule, AXImageModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ax-avatar [size]=\"size()\" class=\"ax-cursor-pointer ax-relative\" [title]=\"title()\"\n class=\"ax-{{ avatarColor() }}-lightest ax-border \">\n @if (hasAvatar()) {\n <ax-image\n (onError)=\"onImageError($event)\"\n (onLoad)=\"onImageLoad($event)\"\n [src]=\"resolvedSrc()\"\n />\n } @else {\n <ax-text>\n <small class=\"ax-font-semibold\" [style.font-size]=\"size() * 0.35 + 'px'\">{{ avatarText() }}</small>\n </ax-text>\n }\n</ax-avatar>\n", styles: [":host ax-text{border-style:none;background-color:transparent;color:unset!important}:host ax-image{position:absolute!important;inset:0;width:100%!important;height:100%!important}:host ax-image img{display:block!important}\n"] }]
353
353
  }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], fullName: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullName", required: false }] }], fallbackText: [{ type: i0.Input, args: [{ isSignal: true, alias: "fallbackText", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
354
354
 
355
355
  const AXP_TASK_BADGE_PROVIDERS = new InjectionToken('AXP_TASK_BADGE_PROVIDERS');
@@ -9226,7 +9226,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
9226
9226
  class AXPUserAvatarComponent {
9227
9227
  constructor() {
9228
9228
  this.userAvatarService = inject(AXPUserAvatarService);
9229
- this.destroy$ = new Subject();
9230
9229
  this.userInfo = signal(null, ...(ngDevMode ? [{ debugName: "userInfo" }] : /* istanbul ignore next */ []));
9231
9230
  this.size = input(40, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
9232
9231
  this.userId = input('', ...(ngDevMode ? [{ debugName: "userId" }] : /* istanbul ignore next */ []));
@@ -9240,35 +9239,24 @@ class AXPUserAvatarComponent {
9240
9239
  /** Full display name used for avatar initials and external templates. */
9241
9240
  this.title = computed(() => this.resolveDisplayName(this.userInfo()), ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
9242
9241
  this.isOnline = computed(() => this.userInfo()?.status === 'online', ...(ngDevMode ? [{ debugName: "isOnline" }] : /* istanbul ignore next */ []));
9243
- }
9244
- ngOnInit() {
9245
- this.loadUserData();
9246
- }
9247
- ngOnDestroy() {
9248
- this.destroy$.next();
9249
- this.destroy$.complete();
9250
- }
9251
- loadUserData() {
9252
- // Skip if no username provided
9253
- if (!this.userId()) {
9254
- return;
9255
- }
9256
- // Subscribe to the user info observable to get real-time updates
9257
- this.userAvatarService
9258
- .getUserInfo$(this.userId())
9259
- .pipe(takeUntil(this.destroy$))
9260
- .subscribe((userData) => {
9261
- this.userInfo.set(userData);
9262
- // This is a placeholder - replace with your actual avatar URL logic
9263
- this.generateAvatarSrc();
9242
+ effect((onCleanup) => {
9243
+ const userId = this.userId()?.trim();
9244
+ if (!userId) {
9245
+ this.userInfo.set(null);
9246
+ this.src.set('');
9247
+ return;
9248
+ }
9249
+ const sub = this.userAvatarService.getUserInfo$(userId).subscribe((userData) => {
9250
+ this.userInfo.set(userData);
9251
+ this.generateAvatarSrc();
9252
+ });
9253
+ onCleanup(() => sub.unsubscribe());
9264
9254
  });
9265
9255
  }
9266
9256
  /**
9267
9257
  * Resolves avatar image URL from user data and resets load state.
9268
9258
  */
9269
9259
  generateAvatarSrc() {
9270
- // Example: Check if the user has a custom avatar URL
9271
- // If not, generate a placeholder using initials
9272
9260
  if (this.userInfo()?.avatarUrl) {
9273
9261
  this.src.set(this.userInfo()?.avatarUrl);
9274
9262
  return;
@@ -9291,7 +9279,7 @@ class AXPUserAvatarComponent {
9291
9279
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPUserAvatarComponent, decorators: [{
9292
9280
  type: Component,
9293
9281
  args: [{ selector: 'axp-user-avatar', imports: [AXPAvatarComponent, AXBadgeModule, AXSkeletonModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [], template: "<axp-avatar [size]=\"size()\" [src]=\"src()\" [fullName]=\"title()\" />\n" }]
9294
- }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userId: [{ type: i0.Input, args: [{ isSignal: true, alias: "userId", required: false }] }] } });
9282
+ }], ctorParameters: () => [], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userId: [{ type: i0.Input, args: [{ isSignal: true, alias: "userId", required: false }] }] } });
9295
9283
 
9296
9284
  //#region ---- Imports ----
9297
9285
  //#endregion