valtech-components 2.0.988 → 2.0.989
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.
- package/esm2022/lib/components/atoms/button/button.component.mjs +6 -3
- package/esm2022/lib/components/organisms/edit-org-modal/edit-org-modal.component.mjs +229 -0
- package/esm2022/lib/components/organisms/edit-org-modal/edit-org-modal.i18n.mjs +38 -0
- package/esm2022/lib/components/organisms/invite-member-modal/invite-member-modal.component.mjs +519 -0
- package/esm2022/lib/components/organisms/invite-member-modal/invite-member-modal.i18n.mjs +54 -0
- package/esm2022/lib/components/organisms/member-detail-modal/member-detail-modal.component.mjs +406 -0
- package/esm2022/lib/components/organisms/member-detail-modal/member-detail-modal.i18n.mjs +72 -0
- package/esm2022/lib/components/organisms/member-detail-modal/types.mjs +2 -0
- package/esm2022/lib/components/organisms/transfer-ownership-modal/transfer-ownership-modal.component.mjs +231 -0
- package/esm2022/lib/components/organisms/transfer-ownership-modal/transfer-ownership-modal.i18n.mjs +27 -0
- package/esm2022/lib/components/organisms/transfer-ownership-modal/types.mjs +2 -0
- package/esm2022/lib/components/types.mjs +1 -1
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +7 -1
- package/fesm2022/valtech-components.mjs +1543 -30
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/article/article.component.d.ts +1 -0
- package/lib/components/organisms/edit-org-modal/edit-org-modal.component.d.ts +49 -0
- package/lib/components/organisms/edit-org-modal/edit-org-modal.i18n.d.ts +7 -0
- package/lib/components/organisms/invite-member-modal/invite-member-modal.component.d.ts +74 -0
- package/lib/components/organisms/invite-member-modal/invite-member-modal.i18n.d.ts +7 -0
- package/lib/components/organisms/member-detail-modal/member-detail-modal.component.d.ts +67 -0
- package/lib/components/organisms/member-detail-modal/member-detail-modal.i18n.d.ts +7 -0
- package/lib/components/organisms/member-detail-modal/types.d.ts +17 -0
- package/lib/components/organisms/transfer-ownership-modal/transfer-ownership-modal.component.d.ts +44 -0
- package/lib/components/organisms/transfer-ownership-modal/transfer-ownership-modal.i18n.d.ts +8 -0
- package/lib/components/organisms/transfer-ownership-modal/types.d.ts +11 -0
- package/lib/components/types.d.ts +2 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +6 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { inject, InjectionToken, makeEnvironmentProviders, APP_INITIALIZER, ErrorHandler, Injectable, DestroyRef, Inject, signal, computed, PLATFORM_ID, isDevMode, Optional, runInInjectionContext, effect, Pipe, TemplateRef, ViewContainerRef, input, Directive, EventEmitter, Component, Input, Output, ChangeDetectionStrategy, HostBinding, HostListener, NgZone, ViewChild, ChangeDetectorRef, output, ContentChild, ElementRef, viewChild, untracked, Injector, isSignal, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import { BehaviorSubject, throwError, Subject, map, distinctUntilChanged, filter as filter$1, take as take$1, firstValueFrom, of, from, EMPTY, Observable, interval, debounceTime, switchMap as switchMap$1, catchError as catchError$1, takeUntil, isObservable, shareReplay, race, timer, forkJoin } from 'rxjs';
|
|
4
|
-
import { catchError, switchMap, finalize, filter, take, map as map$1, tap, retry, timeout, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
|
|
4
|
+
import { catchError, switchMap, finalize, filter, take, map as map$1, tap, distinctUntilChanged as distinctUntilChanged$1, retry, timeout, debounceTime as debounceTime$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
|
|
5
5
|
import * as i1$3 from '@angular/common/http';
|
|
6
6
|
import { provideHttpClient, withInterceptors, HttpClient, HttpErrorResponse } from '@angular/common/http';
|
|
7
7
|
import * as i1$1 from '@angular/fire/firestore';
|
|
8
|
-
import { provideFirestore, getFirestore, connectFirestoreEmulator, enableIndexedDbPersistence, doc, getDoc, collection, query as query$1, getDocs, getCountFromServer, limit, docData, collectionData, serverTimestamp, addDoc, setDoc, updateDoc, deleteDoc, writeBatch, arrayUnion, arrayRemove, increment, where, orderBy, startAfter, startAt, endBefore, endAt, Timestamp, onSnapshot } from '@angular/fire/firestore';
|
|
8
|
+
import { provideFirestore, getFirestore, connectFirestoreEmulator, enableIndexedDbPersistence, doc, getDoc, collection, query as query$1, getDocs, getCountFromServer, limit, docData, collectionData, serverTimestamp, addDoc, setDoc, updateDoc, deleteDoc, writeBatch, arrayUnion, arrayRemove, increment, where, orderBy, startAfter, startAt, endBefore, endAt, Timestamp, onSnapshot, Firestore } from '@angular/fire/firestore';
|
|
9
9
|
import * as i1$5 from '@angular/common';
|
|
10
10
|
import { isPlatformBrowser, CommonModule, NgStyle, NgFor, DOCUMENT, NgClass, TitleCasePipe } from '@angular/common';
|
|
11
11
|
import { provideAnalytics, getAnalytics, Analytics, logEvent, setUserId, setUserProperties } from '@angular/fire/analytics';
|
|
@@ -54,7 +54,7 @@ import 'prismjs/components/prism-json';
|
|
|
54
54
|
* Current version of valtech-components.
|
|
55
55
|
* This is automatically updated during the publish process.
|
|
56
56
|
*/
|
|
57
|
-
const VERSION = '2.0.
|
|
57
|
+
const VERSION = '2.0.989';
|
|
58
58
|
|
|
59
59
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
60
60
|
let isRefreshing = false;
|
|
@@ -10497,6 +10497,7 @@ class ButtonComponent {
|
|
|
10497
10497
|
[fill]="resolvedProps.fill"
|
|
10498
10498
|
[size]="resolvedProps.size"
|
|
10499
10499
|
[href]="resolvedProps.href"
|
|
10500
|
+
[routerLink]="resolvedProps.routerLink ?? null"
|
|
10500
10501
|
[target]="resolvedProps.target"
|
|
10501
10502
|
[shape]="resolvedProps.shape"
|
|
10502
10503
|
(click)="clickHandler()"
|
|
@@ -10507,11 +10508,11 @@ class ButtonComponent {
|
|
|
10507
10508
|
<ion-spinner *ngIf="resolvedProps.state === states.WORKING" name="circular"></ion-spinner>
|
|
10508
10509
|
<ion-text *ngIf="resolvedProps.state !== states.WORKING">{{ displayText }}</ion-text>
|
|
10509
10510
|
</ion-button>
|
|
10510
|
-
`, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;min-width:6.25rem;margin:0}ion-button.small{--padding-bottom: 12px;--padding-end: 14px;--padding-start: 14px;--padding-top: 12px}ion-button.button-clear{padding:0;margin:0}ion-button ion-spinner{--color: currentColor}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
|
|
10511
|
+
`, isInline: true, styles: ["@charset \"UTF-8\";:root{--val-container-sm: 540px;--val-container-md: 720px;--val-container-lg: 880px;--val-container-xl: 1100px;--val-container-padding: 16px;--ion-color-primary: #7026df;--ion-color-primary-rgb: 112, 38, 223;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #6321c4;--ion-color-primary-tint: #7e3ce2;--ion-color-secondary: #e2ccff;--ion-color-secondary-rgb: 226, 204, 255;--ion-color-secondary-contrast: #000000;--ion-color-secondary-contrast-rgb: 0, 0, 0;--ion-color-secondary-shade: #c7b4e0;--ion-color-secondary-tint: #e5d1ff;--ion-color-texti: #354c69;--ion-color-texti-rgb: 53, 76, 105;--ion-color-texti-contrast: #ffffff;--ion-color-texti-contrast-rgb: 255, 255, 255;--ion-color-texti-shade: #2f435c;--ion-color-texti-tint: #495e78;--ion-color-darki: #090f1b;--ion-color-darki-rgb: 9, 15, 27;--ion-color-darki-contrast: #ffffff;--ion-color-darki-contrast-rgb: 255, 255, 255;--ion-color-darki-shade: #080d18;--ion-color-darki-tint: #222732;--ion-color-medium: #9e9e9e;--ion-color-medium-rgb: 158, 158, 158;--ion-color-medium-contrast: #000000;--ion-color-medium-contrast-rgb: 0, 0, 0;--ion-color-medium-shade: #8b8b8b;--ion-color-medium-tint: #a8a8a8;--swiper-pagination-color: var(--ion-color-primary);--swiper-navigation-color: var(--ion-color-primary);--swiper-pagination-bullet-inactive-color: var(--ion-color-medium)}body.dark,html.ion-palette-dark,body[data-theme=dark]{--ion-color-texti: #8fc1ff;--ion-color-texti-rgb: 143, 193, 255;--ion-color-texti-contrast: #000000;--ion-color-texti-contrast-rgb: 0, 0, 0;--ion-color-texti-shade: #7eaae0;--ion-color-texti-tint: #9ac7ff;--ion-color-darki: #ffffff;--ion-color-darki-rgb: 255, 255, 255;--ion-color-darki-contrast: #000000;--ion-color-darki-contrast-rgb: 0, 0, 0;--ion-color-darki-shade: #e0e0e0;--ion-color-darki-tint: #ffffff;--ion-color-primary: #8f49f8;--ion-color-primary-rgb: 143, 73, 248;--ion-color-primary-contrast: #ffffff;--ion-color-primary-contrast-rgb: 255, 255, 255;--ion-color-primary-shade: #7e40da;--ion-color-primary-tint: #9a5bf9}.ion-color-texti{--ion-color-base: var(--ion-color-texti);--ion-color-base-rgb: var(--ion-color-texti-rgb);--ion-color-contrast: var(--ion-color-texti-contrast);--ion-color-contrast-rgb: var(--ion-color-texti-contrast-rgb);--ion-color-shade: var(--ion-color-texti-shade);--ion-color-tint: var(--ion-color-texti-tint)}.ion-color-darki{--ion-color-base: var(--ion-color-darki);--ion-color-base-rgb: var(--ion-color-darki-rgb);--ion-color-contrast: var(--ion-color-darki-contrast);--ion-color-contrast-rgb: var(--ion-color-darki-contrast-rgb);--ion-color-shade: var(--ion-color-darki-shade);--ion-color-tint: var(--ion-color-darki-tint)}ion-button{font-family:var(--ion-default-font),Arial,sans-serif;min-width:6.25rem;margin:0}ion-button.small{--padding-bottom: 12px;--padding-end: 14px;--padding-start: 14px;--padding-top: 12px}ion-button.button-clear{padding:0;margin:0}ion-button ion-spinner{--color: currentColor}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }] }); }
|
|
10511
10512
|
}
|
|
10512
10513
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
10513
10514
|
type: Component,
|
|
10514
|
-
args: [{ selector: 'val-button', standalone: true, imports: [CommonModule, IonButton, IonIcon, IonSpinner, IonText], template: `
|
|
10515
|
+
args: [{ selector: 'val-button', standalone: true, imports: [CommonModule, RouterLink, IonButton, IonIcon, IonSpinner, IonText], template: `
|
|
10515
10516
|
<ion-button
|
|
10516
10517
|
[attr.data-testid]="resolvedProps.token"
|
|
10517
10518
|
[type]="resolvedProps.type"
|
|
@@ -10520,6 +10521,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
10520
10521
|
[fill]="resolvedProps.fill"
|
|
10521
10522
|
[size]="resolvedProps.size"
|
|
10522
10523
|
[href]="resolvedProps.href"
|
|
10524
|
+
[routerLink]="resolvedProps.routerLink ?? null"
|
|
10523
10525
|
[target]="resolvedProps.target"
|
|
10524
10526
|
[shape]="resolvedProps.shape"
|
|
10525
10527
|
(click)="clickHandler()"
|
|
@@ -41735,7 +41737,7 @@ const PROFILE_VIEW_I18N = {
|
|
|
41735
41737
|
const HANDLE_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
41736
41738
|
const HANDLE_MIN = 3;
|
|
41737
41739
|
const HANDLE_MAX = 20;
|
|
41738
|
-
const DEFAULT_NAMESPACE$
|
|
41740
|
+
const DEFAULT_NAMESPACE$b = 'Settings.Profile';
|
|
41739
41741
|
/**
|
|
41740
41742
|
* `val-profile-view` — vista Perfil full-feature autocontenida (organism).
|
|
41741
41743
|
*
|
|
@@ -41785,7 +41787,7 @@ class ProfileViewComponent {
|
|
|
41785
41787
|
showPhone: merged.showPhone ?? true,
|
|
41786
41788
|
showShareCta: merged.showShareCta ?? true,
|
|
41787
41789
|
profileBaseUrl: merged.profileBaseUrl ?? '',
|
|
41788
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
41790
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$b,
|
|
41789
41791
|
onSaved: merged.onSaved,
|
|
41790
41792
|
onAvatarUploaded: merged.onAvatarUploaded,
|
|
41791
41793
|
};
|
|
@@ -42701,7 +42703,7 @@ const PREFERENCES_VIEW_I18N = {
|
|
|
42701
42703
|
},
|
|
42702
42704
|
};
|
|
42703
42705
|
|
|
42704
|
-
const DEFAULT_NAMESPACE$
|
|
42706
|
+
const DEFAULT_NAMESPACE$a = 'Settings.General';
|
|
42705
42707
|
const DEFAULT_LANGUAGES = ['es', 'en'];
|
|
42706
42708
|
/**
|
|
42707
42709
|
* `val-preferences-view` — vista de preferencias de UI cross-app (tema +
|
|
@@ -42738,7 +42740,7 @@ class PreferencesViewComponent {
|
|
|
42738
42740
|
showLanguage: merged.showLanguage ?? true,
|
|
42739
42741
|
showFontSize: merged.showFontSize ?? true,
|
|
42740
42742
|
supportedLanguages: merged.supportedLanguages ?? DEFAULT_LANGUAGES,
|
|
42741
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
42743
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$a,
|
|
42742
42744
|
onThemeChanged: merged.onThemeChanged,
|
|
42743
42745
|
onLanguageChanged: merged.onLanguageChanged,
|
|
42744
42746
|
onFontSizeChanged: merged.onFontSizeChanged,
|
|
@@ -44550,7 +44552,7 @@ const SECURITY_VIEW_I18N = {
|
|
|
44550
44552
|
};
|
|
44551
44553
|
|
|
44552
44554
|
addIcons({ laptopOutline, phonePortraitOutline });
|
|
44553
|
-
const DEFAULT_NAMESPACE$
|
|
44555
|
+
const DEFAULT_NAMESPACE$9 = 'Settings.Security';
|
|
44554
44556
|
/**
|
|
44555
44557
|
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
44556
44558
|
*
|
|
@@ -44599,7 +44601,7 @@ class SecurityViewComponent {
|
|
|
44599
44601
|
showChangeEmail: merged.showChangeEmail ?? true,
|
|
44600
44602
|
showMfa: merged.showMfa ?? true,
|
|
44601
44603
|
showPolicies: merged.showPolicies ?? true,
|
|
44602
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
44604
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$9,
|
|
44603
44605
|
handleDeepLinks: merged.handleDeepLinks ?? true,
|
|
44604
44606
|
homeRoute: merged.homeRoute ?? '/app/home',
|
|
44605
44607
|
onMfaCompleted: merged.onMfaCompleted,
|
|
@@ -45505,7 +45507,7 @@ const CREATE_ORG_MODAL_I18N = {
|
|
|
45505
45507
|
},
|
|
45506
45508
|
};
|
|
45507
45509
|
|
|
45508
|
-
const DEFAULT_NAMESPACE$
|
|
45510
|
+
const DEFAULT_NAMESPACE$8 = 'CreateOrgModal';
|
|
45509
45511
|
/**
|
|
45510
45512
|
* `val-create-org-modal` — modal de creación de organización (organism
|
|
45511
45513
|
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
@@ -45531,10 +45533,10 @@ class CreateOrgModalComponent {
|
|
|
45531
45533
|
this.toast = inject(ToastService);
|
|
45532
45534
|
this.errors = inject(ValtechErrorService);
|
|
45533
45535
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45534
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45536
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$8;
|
|
45535
45537
|
this._busy = signal(false);
|
|
45536
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45537
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45538
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$8)) {
|
|
45539
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$8, CREATE_ORG_MODAL_I18N);
|
|
45538
45540
|
}
|
|
45539
45541
|
this.formMeta = signal(this.buildFormMeta());
|
|
45540
45542
|
effect(() => {
|
|
@@ -45770,7 +45772,7 @@ const DELETE_ACCOUNT_MODAL_I18N = {
|
|
|
45770
45772
|
},
|
|
45771
45773
|
};
|
|
45772
45774
|
|
|
45773
|
-
const DEFAULT_NAMESPACE$
|
|
45775
|
+
const DEFAULT_NAMESPACE$7 = 'Settings.DeleteAccount';
|
|
45774
45776
|
/**
|
|
45775
45777
|
* `val-delete-account-modal` — modal de eliminación de cuenta (organism,
|
|
45776
45778
|
* cuenta-específico). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -45796,7 +45798,7 @@ class DeleteAccountModalComponent {
|
|
|
45796
45798
|
this.i18n = inject(I18nService);
|
|
45797
45799
|
this.toast = inject(ToastService);
|
|
45798
45800
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45799
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45801
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$7;
|
|
45800
45802
|
this.hasPassword = signal(null);
|
|
45801
45803
|
this.codeSent = signal(false);
|
|
45802
45804
|
this.formState = signal(ComponentStates.ENABLED);
|
|
@@ -45863,8 +45865,8 @@ class DeleteAccountModalComponent {
|
|
|
45863
45865
|
],
|
|
45864
45866
|
actions: this.submitBtn('delete-code-submit', 'confirmCta'),
|
|
45865
45867
|
}));
|
|
45866
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45867
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45868
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$7)) {
|
|
45869
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$7, DELETE_ACCOUNT_MODAL_I18N);
|
|
45868
45870
|
}
|
|
45869
45871
|
}
|
|
45870
45872
|
ngOnInit() {
|
|
@@ -46065,7 +46067,7 @@ const ORG_INFO_SHEET_I18N = {
|
|
|
46065
46067
|
},
|
|
46066
46068
|
};
|
|
46067
46069
|
|
|
46068
|
-
const DEFAULT_NAMESPACE$
|
|
46070
|
+
const DEFAULT_NAMESPACE$6 = 'OrgInfoSheet';
|
|
46069
46071
|
/**
|
|
46070
46072
|
* `val-org-info-sheet` — sheet informativo "¿Qué son las organizaciones?".
|
|
46071
46073
|
* Extraído del `OrgInfoSheetComponent` inline de `AccountPage` bajo el proceso de
|
|
@@ -46110,15 +46112,15 @@ class OrgInfoSheetComponent {
|
|
|
46110
46112
|
text: this.closeProps.text || this.resolvedCloseLabel(),
|
|
46111
46113
|
}));
|
|
46112
46114
|
addIcons({ peopleOutline, swapHorizontalOutline, mailOutline });
|
|
46113
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46114
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46115
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$6)) {
|
|
46116
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$6, ORG_INFO_SHEET_I18N);
|
|
46115
46117
|
}
|
|
46116
46118
|
}
|
|
46117
46119
|
dismiss() {
|
|
46118
46120
|
this._modalRef?.dismiss(null, 'cancel');
|
|
46119
46121
|
}
|
|
46120
46122
|
tt(key) {
|
|
46121
|
-
return this.i18n.t(key, DEFAULT_NAMESPACE$
|
|
46123
|
+
return this.i18n.t(key, DEFAULT_NAMESPACE$6);
|
|
46122
46124
|
}
|
|
46123
46125
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46124
46126
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: OrgInfoSheetComponent, isStandalone: true, selector: "val-org-info-sheet", inputs: { title: "title", subtitle: "subtitle", body: "body", closeLabel: "closeLabel", closeProps: "closeProps", _modalRef: "_modalRef" }, ngImport: i0, template: `
|
|
@@ -46285,7 +46287,7 @@ const SWITCH_ORG_MODAL_I18N = {
|
|
|
46285
46287
|
},
|
|
46286
46288
|
};
|
|
46287
46289
|
|
|
46288
|
-
const DEFAULT_NAMESPACE$
|
|
46290
|
+
const DEFAULT_NAMESPACE$5 = 'Settings.SwitchOrg';
|
|
46289
46291
|
addIcons({ businessOutline, checkmarkCircleOutline });
|
|
46290
46292
|
/**
|
|
46291
46293
|
* `val-switch-org-modal` — modal de cambio de organización activa (organism
|
|
@@ -46311,7 +46313,7 @@ class SwitchOrgModalComponent {
|
|
|
46311
46313
|
this.orgSwitch = inject(OrgSwitchService);
|
|
46312
46314
|
this.errors = inject(ValtechErrorService);
|
|
46313
46315
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
46314
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
46316
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$5;
|
|
46315
46317
|
this.orgs = signal([]);
|
|
46316
46318
|
this.loading = signal(false);
|
|
46317
46319
|
this.query = signal('');
|
|
@@ -46327,8 +46329,8 @@ class SwitchOrgModalComponent {
|
|
|
46327
46329
|
return list;
|
|
46328
46330
|
return list.filter(o => o.name.toLowerCase().includes(q));
|
|
46329
46331
|
});
|
|
46330
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46331
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46332
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$5)) {
|
|
46333
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$5, SWITCH_ORG_MODAL_I18N);
|
|
46332
46334
|
}
|
|
46333
46335
|
this.loadOrgs();
|
|
46334
46336
|
}
|
|
@@ -46646,7 +46648,7 @@ const ACCOUNT_VIEW_I18N = {
|
|
|
46646
46648
|
};
|
|
46647
46649
|
|
|
46648
46650
|
addIcons({ peopleOutline, businessOutline, chevronForwardOutline, swapHorizontalOutline, mailOutline });
|
|
46649
|
-
const DEFAULT_NAMESPACE = 'Settings.Account';
|
|
46651
|
+
const DEFAULT_NAMESPACE$4 = 'Settings.Account';
|
|
46650
46652
|
const DEFAULT_MANAGE_ORG_ROUTE = '/app/settings/organization';
|
|
46651
46653
|
/**
|
|
46652
46654
|
* `val-account-view` — vista Cuenta full-feature autocontenida (organism).
|
|
@@ -46687,7 +46689,7 @@ class AccountViewComponent {
|
|
|
46687
46689
|
showNewOrgCta: merged.showNewOrgCta ?? true,
|
|
46688
46690
|
showLogout: merged.showLogout ?? true,
|
|
46689
46691
|
showDeleteAccount: merged.showDeleteAccount ?? true,
|
|
46690
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
46692
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$4,
|
|
46691
46693
|
manageOrgRoute: merged.manageOrgRoute ?? DEFAULT_MANAGE_ORG_ROUTE,
|
|
46692
46694
|
onOrgSwitched: merged.onOrgSwitched,
|
|
46693
46695
|
onOrgCreated: merged.onOrgCreated,
|
|
@@ -47374,6 +47376,1517 @@ function provideValtechAccountRoutes(opts) {
|
|
|
47374
47376
|
];
|
|
47375
47377
|
}
|
|
47376
47378
|
|
|
47379
|
+
/**
|
|
47380
|
+
* Defaults i18n (es/en) embebidos en `val-invite-member-modal`. Auto-registrados
|
|
47381
|
+
* en el constructor del componente si el consumer no proveyó el namespace
|
|
47382
|
+
* (`InviteModal` por default). SOLO incluye las keys que el modal usa.
|
|
47383
|
+
*/
|
|
47384
|
+
const INVITE_MEMBER_MODAL_I18N = {
|
|
47385
|
+
es: {
|
|
47386
|
+
title: 'Invitar miembro',
|
|
47387
|
+
subtitle: 'Busca por handle o escribe un correo para invitar.',
|
|
47388
|
+
searchPlaceholder: 'Handle (@usuario) o correo...',
|
|
47389
|
+
searchingLabel: 'Buscando...',
|
|
47390
|
+
noResults: 'No se encontraron usuarios.',
|
|
47391
|
+
inviteByEmail: 'Invitar por correo a:',
|
|
47392
|
+
sendInvite: 'Enviar invitación',
|
|
47393
|
+
sending: 'Enviando...',
|
|
47394
|
+
success: 'Invitación enviada.',
|
|
47395
|
+
successPlural: 'Invitaciones enviadas.',
|
|
47396
|
+
close: 'Cerrar',
|
|
47397
|
+
errorInvalid: 'Ingresa un handle o correo válido.',
|
|
47398
|
+
sendSelected: 'Invitar seleccionados',
|
|
47399
|
+
selectedLabel: 'Seleccionados',
|
|
47400
|
+
roleLabel: 'Rol',
|
|
47401
|
+
roleViewer: 'Visor',
|
|
47402
|
+
roleViewerDesc: 'Solo lectura',
|
|
47403
|
+
roleEditor: 'Editor',
|
|
47404
|
+
roleEditorDesc: 'Puede editar contenido',
|
|
47405
|
+
roleAdmin: 'Administrador',
|
|
47406
|
+
roleAdminDesc: 'Gestión completa',
|
|
47407
|
+
},
|
|
47408
|
+
en: {
|
|
47409
|
+
title: 'Invite member',
|
|
47410
|
+
subtitle: 'Search by handle or enter an email to invite.',
|
|
47411
|
+
searchPlaceholder: 'Handle (@user) or email...',
|
|
47412
|
+
searchingLabel: 'Searching...',
|
|
47413
|
+
noResults: 'No users found.',
|
|
47414
|
+
inviteByEmail: 'Invite by email:',
|
|
47415
|
+
sendInvite: 'Send invitation',
|
|
47416
|
+
sending: 'Sending...',
|
|
47417
|
+
success: 'Invitation sent.',
|
|
47418
|
+
successPlural: 'Invitations sent.',
|
|
47419
|
+
close: 'Close',
|
|
47420
|
+
errorInvalid: 'Enter a valid handle or email.',
|
|
47421
|
+
sendSelected: 'Invite selected',
|
|
47422
|
+
selectedLabel: 'Selected',
|
|
47423
|
+
roleLabel: 'Role',
|
|
47424
|
+
roleViewer: 'Viewer',
|
|
47425
|
+
roleViewerDesc: 'Read only',
|
|
47426
|
+
roleEditor: 'Editor',
|
|
47427
|
+
roleEditorDesc: 'Can edit content',
|
|
47428
|
+
roleAdmin: 'Admin',
|
|
47429
|
+
roleAdminDesc: 'Full management',
|
|
47430
|
+
},
|
|
47431
|
+
};
|
|
47432
|
+
|
|
47433
|
+
const DEFAULT_NAMESPACE$3 = 'InviteModal';
|
|
47434
|
+
addIcons({ personOutline, mailOutline, closeOutline, checkmarkCircleOutline });
|
|
47435
|
+
/**
|
|
47436
|
+
* `val-invite-member-modal` — invitación de miembros a una organización.
|
|
47437
|
+
* Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
47438
|
+
*
|
|
47439
|
+
* Busca usuarios por handle en Firestore `/profiles` (multi-select) o invita por
|
|
47440
|
+
* email cuando el query es un correo válido. Asigna el rol seleccionado y envía la
|
|
47441
|
+
* invitación vía `OrgService.inviteUser`. Excluye al usuario actual y a los
|
|
47442
|
+
* `existingMemberIds` de los resultados.
|
|
47443
|
+
*
|
|
47444
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
47445
|
+
* `onSuccess`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar texto en
|
|
47446
|
+
* `slot=end`, título/subtítulo en el body con `val-display`/`val-title`.
|
|
47447
|
+
*
|
|
47448
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
47449
|
+
* `InviteModal`.
|
|
47450
|
+
*/
|
|
47451
|
+
class InviteMemberModalComponent {
|
|
47452
|
+
constructor() {
|
|
47453
|
+
this.orgService = inject(OrgService);
|
|
47454
|
+
this.auth = inject(AuthService);
|
|
47455
|
+
this.toast = inject(ToastService);
|
|
47456
|
+
this.errors = inject(ValtechErrorService);
|
|
47457
|
+
this.firestore = inject(Firestore);
|
|
47458
|
+
this.i18n = inject(I18nService);
|
|
47459
|
+
/** Organización a la que se invita. */
|
|
47460
|
+
this.orgId = '';
|
|
47461
|
+
/** Ids de miembros ya existentes (excluidos de los resultados). */
|
|
47462
|
+
this.existingMemberIds = [];
|
|
47463
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47464
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$3;
|
|
47465
|
+
this.query = signal('');
|
|
47466
|
+
this.searching = signal(false);
|
|
47467
|
+
this.searchResults = signal([]);
|
|
47468
|
+
this.selectedUsers = signal([]);
|
|
47469
|
+
this.sending = signal(false);
|
|
47470
|
+
this.selectedRole = signal('viewer');
|
|
47471
|
+
this.availableRoles = signal([
|
|
47472
|
+
{ id: 'viewer', name: 'viewer' },
|
|
47473
|
+
{ id: 'editor', name: 'editor' },
|
|
47474
|
+
{ id: 'admin', name: 'admin' },
|
|
47475
|
+
]);
|
|
47476
|
+
this.roleControl = new FormControl('viewer');
|
|
47477
|
+
this.roleSelectProps = computed(() => ({
|
|
47478
|
+
control: this.roleControl,
|
|
47479
|
+
label: '',
|
|
47480
|
+
placeholder: this.t('roleLabel'),
|
|
47481
|
+
type: InputType.SELECT,
|
|
47482
|
+
state: ComponentStates.ENABLED,
|
|
47483
|
+
options: this.availableRoles().map(r => ({
|
|
47484
|
+
id: r.id,
|
|
47485
|
+
name: this.roleDisplayName(r),
|
|
47486
|
+
order: 0,
|
|
47487
|
+
})),
|
|
47488
|
+
}));
|
|
47489
|
+
this.isEmail = computed(() => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(this.query().trim()));
|
|
47490
|
+
this.sendButtonProps = computed(() => ({
|
|
47491
|
+
text: this.t('sendInvite'),
|
|
47492
|
+
token: 'invite-submit-email',
|
|
47493
|
+
color: 'primary',
|
|
47494
|
+
fill: 'solid',
|
|
47495
|
+
expand: 'block',
|
|
47496
|
+
size: 'default',
|
|
47497
|
+
type: 'button',
|
|
47498
|
+
state: this.sending() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47499
|
+
}));
|
|
47500
|
+
this.sendSelectedProps = computed(() => ({
|
|
47501
|
+
text: `${this.t('sendSelected')} (${this.selectedUsers().length})`,
|
|
47502
|
+
token: 'invite-submit',
|
|
47503
|
+
color: 'primary',
|
|
47504
|
+
fill: 'solid',
|
|
47505
|
+
expand: 'block',
|
|
47506
|
+
size: 'default',
|
|
47507
|
+
type: 'button',
|
|
47508
|
+
state: this.sending() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47509
|
+
}));
|
|
47510
|
+
this.searchSubject = new Subject();
|
|
47511
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$3)) {
|
|
47512
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$3, INVITE_MEMBER_MODAL_I18N);
|
|
47513
|
+
}
|
|
47514
|
+
this.loadRoles();
|
|
47515
|
+
this.roleSub = this.roleControl.valueChanges.subscribe(v => {
|
|
47516
|
+
if (v)
|
|
47517
|
+
this.selectedRole.set(v);
|
|
47518
|
+
});
|
|
47519
|
+
// val-searchbar already debounces -- pipeline only needs distinctUntilChanged + switchMap
|
|
47520
|
+
this.searchSubject
|
|
47521
|
+
.pipe(distinctUntilChanged$1(), switchMap(q => {
|
|
47522
|
+
if (!q || q.length < 2 || this.isEmail()) {
|
|
47523
|
+
this.searching.set(false);
|
|
47524
|
+
this.searchResults.set([]);
|
|
47525
|
+
return [];
|
|
47526
|
+
}
|
|
47527
|
+
const cleanQ = (q.startsWith('@') ? q.slice(1) : q).toLowerCase();
|
|
47528
|
+
const q$ = query$1(collection(this.firestore, 'profiles'), orderBy('handle'), startAt(cleanQ), endAt(cleanQ + ''), limit(8));
|
|
47529
|
+
return from(getDocs(q$)).pipe(map$1(snap => ({
|
|
47530
|
+
users: snap.docs.map(d => ({
|
|
47531
|
+
userId: d.id,
|
|
47532
|
+
handle: d.data()['handle'],
|
|
47533
|
+
name: d.data()['name'],
|
|
47534
|
+
})),
|
|
47535
|
+
})));
|
|
47536
|
+
}))
|
|
47537
|
+
.subscribe({
|
|
47538
|
+
next: res => {
|
|
47539
|
+
if (res && 'users' in res) {
|
|
47540
|
+
const currentUserId = this.auth.user()?.userId;
|
|
47541
|
+
const excluded = new Set([
|
|
47542
|
+
...(currentUserId ? [currentUserId] : []),
|
|
47543
|
+
...this.existingMemberIds,
|
|
47544
|
+
]);
|
|
47545
|
+
this.searchResults.set(res.users.filter(u => !excluded.has(u.userId)));
|
|
47546
|
+
}
|
|
47547
|
+
this.searching.set(false);
|
|
47548
|
+
},
|
|
47549
|
+
error: () => {
|
|
47550
|
+
this.searchResults.set([]);
|
|
47551
|
+
this.searching.set(false);
|
|
47552
|
+
},
|
|
47553
|
+
});
|
|
47554
|
+
}
|
|
47555
|
+
onQueryChange(value) {
|
|
47556
|
+
this.query.set(value ?? '');
|
|
47557
|
+
if (!this.isEmail() && (value ?? '').length >= 2) {
|
|
47558
|
+
this.searching.set(true);
|
|
47559
|
+
}
|
|
47560
|
+
else {
|
|
47561
|
+
this.searching.set(false);
|
|
47562
|
+
this.searchResults.set([]);
|
|
47563
|
+
}
|
|
47564
|
+
this.searchSubject.next(value ?? '');
|
|
47565
|
+
}
|
|
47566
|
+
loadRoles() {
|
|
47567
|
+
if (!this.orgId)
|
|
47568
|
+
return;
|
|
47569
|
+
this.orgService.listOrgRoles(this.orgId).subscribe({
|
|
47570
|
+
next: roles => {
|
|
47571
|
+
if (roles.length)
|
|
47572
|
+
this.availableRoles.set(roles);
|
|
47573
|
+
},
|
|
47574
|
+
});
|
|
47575
|
+
}
|
|
47576
|
+
roleDisplayName(role) {
|
|
47577
|
+
const keyMap = {
|
|
47578
|
+
viewer: 'roleViewer',
|
|
47579
|
+
editor: 'roleEditor',
|
|
47580
|
+
admin: 'roleAdmin',
|
|
47581
|
+
};
|
|
47582
|
+
const key = keyMap[role.name] ?? role.name;
|
|
47583
|
+
const label = this.t(key);
|
|
47584
|
+
return label && !label.startsWith('[') ? label : role.name;
|
|
47585
|
+
}
|
|
47586
|
+
async onInviteByEmail() {
|
|
47587
|
+
const email = this.query().trim();
|
|
47588
|
+
if (!email || this.sending())
|
|
47589
|
+
return;
|
|
47590
|
+
this.sending.set(true);
|
|
47591
|
+
try {
|
|
47592
|
+
await firstValueFrom(this.orgService.inviteUser(this.orgId, {
|
|
47593
|
+
email,
|
|
47594
|
+
roleId: this.selectedRole(),
|
|
47595
|
+
}));
|
|
47596
|
+
this.toast.show({
|
|
47597
|
+
message: this.t('success'),
|
|
47598
|
+
color: 'dark',
|
|
47599
|
+
duration: 3500,
|
|
47600
|
+
});
|
|
47601
|
+
this.onSuccess?.();
|
|
47602
|
+
this.dismiss();
|
|
47603
|
+
}
|
|
47604
|
+
catch (err) {
|
|
47605
|
+
this.errors.handle(err, {
|
|
47606
|
+
context: 'invite.byEmail',
|
|
47607
|
+
fallbackKey: 'sendInvite',
|
|
47608
|
+
i18nNamespace: this.i18nNamespace,
|
|
47609
|
+
});
|
|
47610
|
+
}
|
|
47611
|
+
finally {
|
|
47612
|
+
this.sending.set(false);
|
|
47613
|
+
}
|
|
47614
|
+
}
|
|
47615
|
+
isSelected(userId) {
|
|
47616
|
+
return this.selectedUsers().some(u => u.userId === userId);
|
|
47617
|
+
}
|
|
47618
|
+
toggleUser(user) {
|
|
47619
|
+
if (this.isSelected(user.userId)) {
|
|
47620
|
+
this.selectedUsers.update(list => list.filter(u => u.userId !== user.userId));
|
|
47621
|
+
}
|
|
47622
|
+
else {
|
|
47623
|
+
this.selectedUsers.update(list => [...list, user]);
|
|
47624
|
+
}
|
|
47625
|
+
}
|
|
47626
|
+
async onSendSelected() {
|
|
47627
|
+
const users = this.selectedUsers();
|
|
47628
|
+
if (!users.length || this.sending())
|
|
47629
|
+
return;
|
|
47630
|
+
this.sending.set(true);
|
|
47631
|
+
try {
|
|
47632
|
+
await Promise.all(users.map(u => firstValueFrom(this.orgService.inviteUser(this.orgId, {
|
|
47633
|
+
userId: u.userId,
|
|
47634
|
+
roleId: this.selectedRole(),
|
|
47635
|
+
}))));
|
|
47636
|
+
this.toast.show({
|
|
47637
|
+
message: users.length === 1 ? this.t('success') : this.t('successPlural'),
|
|
47638
|
+
color: 'dark',
|
|
47639
|
+
duration: 3500,
|
|
47640
|
+
});
|
|
47641
|
+
this.selectedUsers.set([]);
|
|
47642
|
+
this.onSuccess?.();
|
|
47643
|
+
this.dismiss();
|
|
47644
|
+
}
|
|
47645
|
+
catch (err) {
|
|
47646
|
+
this.errors.handle(err, {
|
|
47647
|
+
context: 'invite.byUserId',
|
|
47648
|
+
fallbackKey: 'sendInvite',
|
|
47649
|
+
i18nNamespace: this.i18nNamespace,
|
|
47650
|
+
});
|
|
47651
|
+
}
|
|
47652
|
+
finally {
|
|
47653
|
+
this.sending.set(false);
|
|
47654
|
+
}
|
|
47655
|
+
}
|
|
47656
|
+
ngOnDestroy() {
|
|
47657
|
+
this.roleSub?.unsubscribe();
|
|
47658
|
+
}
|
|
47659
|
+
dismiss() {
|
|
47660
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
47661
|
+
}
|
|
47662
|
+
t(key) {
|
|
47663
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
47664
|
+
}
|
|
47665
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InviteMemberModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
47666
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: InviteMemberModalComponent, isStandalone: true, selector: "val-invite-member-modal", inputs: { _modalRef: "_modalRef", orgId: "orgId", existingMemberIds: "existingMemberIds", onSuccess: "onSuccess", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
47667
|
+
<ion-header>
|
|
47668
|
+
<ion-toolbar>
|
|
47669
|
+
<ion-buttons slot="end">
|
|
47670
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
47671
|
+
<strong>{{ t('close') }}</strong>
|
|
47672
|
+
</ion-button>
|
|
47673
|
+
</ion-buttons>
|
|
47674
|
+
</ion-toolbar>
|
|
47675
|
+
</ion-header>
|
|
47676
|
+
|
|
47677
|
+
<ion-content class="ion-padding">
|
|
47678
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
47679
|
+
<val-title
|
|
47680
|
+
[props]="{
|
|
47681
|
+
content: t('subtitle'),
|
|
47682
|
+
size: 'large',
|
|
47683
|
+
color: '',
|
|
47684
|
+
bold: false,
|
|
47685
|
+
}"
|
|
47686
|
+
/>
|
|
47687
|
+
|
|
47688
|
+
<div class="role-select-wrap">
|
|
47689
|
+
<val-title
|
|
47690
|
+
[props]="{
|
|
47691
|
+
content: t('roleLabel'),
|
|
47692
|
+
size: 'small',
|
|
47693
|
+
color: 'dark',
|
|
47694
|
+
bold: false,
|
|
47695
|
+
}"
|
|
47696
|
+
/>
|
|
47697
|
+
<val-select-input data-testid="invite-role-select" [props]="roleSelectProps()" />
|
|
47698
|
+
</div>
|
|
47699
|
+
|
|
47700
|
+
<div class="search-section">
|
|
47701
|
+
<val-searchbar
|
|
47702
|
+
data-testid="invite-search"
|
|
47703
|
+
[props]="{
|
|
47704
|
+
placeholder: t('searchPlaceholder'),
|
|
47705
|
+
debounce: 350,
|
|
47706
|
+
showCancelButton: 'never',
|
|
47707
|
+
}"
|
|
47708
|
+
(filterEvent)="onQueryChange($event)"
|
|
47709
|
+
/>
|
|
47710
|
+
|
|
47711
|
+
@if (searching()) {
|
|
47712
|
+
<div class="search-state">
|
|
47713
|
+
<ion-spinner name="crescent" />
|
|
47714
|
+
<span>{{ t('searchingLabel') }}</span>
|
|
47715
|
+
</div>
|
|
47716
|
+
} @else if (isEmail()) {
|
|
47717
|
+
<div class="email-invite-card">
|
|
47718
|
+
<ion-icon name="mail-outline" class="email-icon" />
|
|
47719
|
+
<div class="email-invite-text">
|
|
47720
|
+
<span class="email-invite-label">{{ t('inviteByEmail') }}</span>
|
|
47721
|
+
<span class="email-invite-address">{{ query().trim() }}</span>
|
|
47722
|
+
</div>
|
|
47723
|
+
</div>
|
|
47724
|
+
<val-button [props]="sendButtonProps()" (click)="onInviteByEmail()" />
|
|
47725
|
+
} @else if (query().length >= 2 && searchResults().length === 0) {
|
|
47726
|
+
<val-empty-state
|
|
47727
|
+
[props]="{
|
|
47728
|
+
variant: 'empty',
|
|
47729
|
+
title: t('noResults'),
|
|
47730
|
+
icon: 'person-outline',
|
|
47731
|
+
}"
|
|
47732
|
+
/>
|
|
47733
|
+
} @else if (searchResults().length > 0) {
|
|
47734
|
+
<div class="results-list">
|
|
47735
|
+
@for (user of searchResults(); track user.userId) {
|
|
47736
|
+
<div
|
|
47737
|
+
class="result-card"
|
|
47738
|
+
[attr.data-testid]="'invite-result-' + user.userId"
|
|
47739
|
+
[class.result-card--selected]="isSelected(user.userId)"
|
|
47740
|
+
(click)="toggleUser(user)"
|
|
47741
|
+
role="checkbox"
|
|
47742
|
+
[attr.aria-checked]="isSelected(user.userId)"
|
|
47743
|
+
>
|
|
47744
|
+
<div class="result-card__avatar">
|
|
47745
|
+
<ion-icon name="person-outline" />
|
|
47746
|
+
</div>
|
|
47747
|
+
<div class="result-card__body">
|
|
47748
|
+
<span class="result-card__name">{{ user.name || user.handle }}</span>
|
|
47749
|
+
@if (user.handle) {
|
|
47750
|
+
<span class="result-card__handle">@{{ user.handle }}</span>
|
|
47751
|
+
}
|
|
47752
|
+
</div>
|
|
47753
|
+
<div class="result-card__check">
|
|
47754
|
+
@if (isSelected(user.userId)) {
|
|
47755
|
+
<ion-icon name="checkmark-circle-outline" class="check-on" />
|
|
47756
|
+
} @else {
|
|
47757
|
+
<div class="check-off"></div>
|
|
47758
|
+
}
|
|
47759
|
+
</div>
|
|
47760
|
+
</div>
|
|
47761
|
+
}
|
|
47762
|
+
</div>
|
|
47763
|
+
}
|
|
47764
|
+
|
|
47765
|
+
@if (selectedUsers().length > 0) {
|
|
47766
|
+
<div class="selected-section">
|
|
47767
|
+
<span class="selected-section__label">{{ t('selectedLabel') }} ({{ selectedUsers().length }})</span>
|
|
47768
|
+
<div class="selected-chips">
|
|
47769
|
+
@for (user of selectedUsers(); track user.userId) {
|
|
47770
|
+
<div class="selected-chip">
|
|
47771
|
+
<span>{{ user.handle ? '@' + user.handle : user.name || user.userId }}</span>
|
|
47772
|
+
<button class="selected-chip__remove" (click)="toggleUser(user)" aria-label="Quitar">×</button>
|
|
47773
|
+
</div>
|
|
47774
|
+
}
|
|
47775
|
+
</div>
|
|
47776
|
+
<val-button [props]="sendSelectedProps()" (click)="onSendSelected()" />
|
|
47777
|
+
</div>
|
|
47778
|
+
}
|
|
47779
|
+
</div>
|
|
47780
|
+
</ion-content>
|
|
47781
|
+
`, isInline: true, styles: ["ion-content{--padding-bottom: 24px}val-display{margin-bottom:4px;display:block}val-title{margin-bottom:8px;display:block}.role-select-wrap{margin-bottom:12px}.role-select{width:100%}val-searchbar{display:block;margin-bottom:4px}.search-section{display:flex;flex-direction:column;gap:14px}.search-state{display:flex;align-items:center;gap:10px;padding:12px 0;color:var(--ion-color-medium);font-size:.88rem}.email-invite-card{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:12px;border:1.5px solid var(--ion-color-primary);background:color-mix(in srgb,var(--ion-color-primary) 8%,transparent)}.email-icon{font-size:24px;color:var(--ion-color-primary);flex-shrink:0}.email-invite-text{display:flex;flex-direction:column;gap:2px}.email-invite-label{font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.email-invite-address{font-weight:600;font-size:.95rem;color:var(--ion-color-dark);word-break:break-all}.results-list{display:flex;flex-direction:column;gap:8px}.result-card{display:flex;align-items:center;gap:14px;padding:12px 14px;border-radius:12px;background:var(--ion-color-light, #f4f5f8);cursor:pointer;transition:opacity .15s}.result-card:active{opacity:.7}:host-context(body.dark) .result-card,:host-context(html.ion-palette-dark) .result-card,:host-context([data-theme=\"dark\"]) .result-card{background:#ffffff0d}.result-card__avatar{width:40px;height:40px;border-radius:50%;background:color-mix(in srgb,var(--ion-color-primary) 15%,transparent);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--ion-color-primary);flex-shrink:0}.result-card__body{display:flex;flex-direction:column;gap:2px}.result-card__name{font-weight:600;font-size:.9rem;color:var(--ion-color-dark)}.result-card__handle{font-size:.78rem;color:var(--ion-color-medium)}.result-card--selected{border:1.5px solid var(--ion-color-primary);background:color-mix(in srgb,var(--ion-color-primary) 8%,transparent)}.result-card__check{flex-shrink:0;margin-left:auto}.check-on{font-size:22px;color:var(--ion-color-primary)}.check-off{width:22px;height:22px;border-radius:50%;border:2px solid var(--ion-color-medium)}.selected-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08));padding-top:14px;display:flex;flex-direction:column;gap:10px}.selected-section__label{font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.selected-chips{display:flex;flex-wrap:wrap;gap:6px}.selected-chip{display:flex;align-items:center;gap:4px;padding:4px 10px 4px 12px;border-radius:20px;background:color-mix(in srgb,var(--ion-color-primary) 12%,transparent);color:var(--ion-color-primary);font-size:.82rem;font-weight:600}.selected-chip__remove{border:none;background:none;cursor:pointer;font-size:1rem;line-height:1;color:var(--ion-color-primary);padding:0 2px;opacity:.7}.selected-chip__remove:hover{opacity:1}\n"], dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "component", type: SearchbarComponent, selector: "val-searchbar", inputs: ["preset", "props"], outputs: ["filterEvent", "focusEvent", "blurEvent"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["preset", "props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }] }); }
|
|
47782
|
+
}
|
|
47783
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InviteMemberModalComponent, decorators: [{
|
|
47784
|
+
type: Component,
|
|
47785
|
+
args: [{ selector: 'val-invite-member-modal', standalone: true, imports: [
|
|
47786
|
+
IonHeader,
|
|
47787
|
+
IonToolbar,
|
|
47788
|
+
IonButtons,
|
|
47789
|
+
IonButton,
|
|
47790
|
+
IonContent,
|
|
47791
|
+
IonSpinner,
|
|
47792
|
+
IonIcon,
|
|
47793
|
+
ReactiveFormsModule,
|
|
47794
|
+
ButtonComponent,
|
|
47795
|
+
DisplayComponent,
|
|
47796
|
+
EmptyStateComponent,
|
|
47797
|
+
SearchbarComponent,
|
|
47798
|
+
SearchSelectorComponent,
|
|
47799
|
+
TextComponent,
|
|
47800
|
+
TitleComponent,
|
|
47801
|
+
], template: `
|
|
47802
|
+
<ion-header>
|
|
47803
|
+
<ion-toolbar>
|
|
47804
|
+
<ion-buttons slot="end">
|
|
47805
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
47806
|
+
<strong>{{ t('close') }}</strong>
|
|
47807
|
+
</ion-button>
|
|
47808
|
+
</ion-buttons>
|
|
47809
|
+
</ion-toolbar>
|
|
47810
|
+
</ion-header>
|
|
47811
|
+
|
|
47812
|
+
<ion-content class="ion-padding">
|
|
47813
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
47814
|
+
<val-title
|
|
47815
|
+
[props]="{
|
|
47816
|
+
content: t('subtitle'),
|
|
47817
|
+
size: 'large',
|
|
47818
|
+
color: '',
|
|
47819
|
+
bold: false,
|
|
47820
|
+
}"
|
|
47821
|
+
/>
|
|
47822
|
+
|
|
47823
|
+
<div class="role-select-wrap">
|
|
47824
|
+
<val-title
|
|
47825
|
+
[props]="{
|
|
47826
|
+
content: t('roleLabel'),
|
|
47827
|
+
size: 'small',
|
|
47828
|
+
color: 'dark',
|
|
47829
|
+
bold: false,
|
|
47830
|
+
}"
|
|
47831
|
+
/>
|
|
47832
|
+
<val-select-input data-testid="invite-role-select" [props]="roleSelectProps()" />
|
|
47833
|
+
</div>
|
|
47834
|
+
|
|
47835
|
+
<div class="search-section">
|
|
47836
|
+
<val-searchbar
|
|
47837
|
+
data-testid="invite-search"
|
|
47838
|
+
[props]="{
|
|
47839
|
+
placeholder: t('searchPlaceholder'),
|
|
47840
|
+
debounce: 350,
|
|
47841
|
+
showCancelButton: 'never',
|
|
47842
|
+
}"
|
|
47843
|
+
(filterEvent)="onQueryChange($event)"
|
|
47844
|
+
/>
|
|
47845
|
+
|
|
47846
|
+
@if (searching()) {
|
|
47847
|
+
<div class="search-state">
|
|
47848
|
+
<ion-spinner name="crescent" />
|
|
47849
|
+
<span>{{ t('searchingLabel') }}</span>
|
|
47850
|
+
</div>
|
|
47851
|
+
} @else if (isEmail()) {
|
|
47852
|
+
<div class="email-invite-card">
|
|
47853
|
+
<ion-icon name="mail-outline" class="email-icon" />
|
|
47854
|
+
<div class="email-invite-text">
|
|
47855
|
+
<span class="email-invite-label">{{ t('inviteByEmail') }}</span>
|
|
47856
|
+
<span class="email-invite-address">{{ query().trim() }}</span>
|
|
47857
|
+
</div>
|
|
47858
|
+
</div>
|
|
47859
|
+
<val-button [props]="sendButtonProps()" (click)="onInviteByEmail()" />
|
|
47860
|
+
} @else if (query().length >= 2 && searchResults().length === 0) {
|
|
47861
|
+
<val-empty-state
|
|
47862
|
+
[props]="{
|
|
47863
|
+
variant: 'empty',
|
|
47864
|
+
title: t('noResults'),
|
|
47865
|
+
icon: 'person-outline',
|
|
47866
|
+
}"
|
|
47867
|
+
/>
|
|
47868
|
+
} @else if (searchResults().length > 0) {
|
|
47869
|
+
<div class="results-list">
|
|
47870
|
+
@for (user of searchResults(); track user.userId) {
|
|
47871
|
+
<div
|
|
47872
|
+
class="result-card"
|
|
47873
|
+
[attr.data-testid]="'invite-result-' + user.userId"
|
|
47874
|
+
[class.result-card--selected]="isSelected(user.userId)"
|
|
47875
|
+
(click)="toggleUser(user)"
|
|
47876
|
+
role="checkbox"
|
|
47877
|
+
[attr.aria-checked]="isSelected(user.userId)"
|
|
47878
|
+
>
|
|
47879
|
+
<div class="result-card__avatar">
|
|
47880
|
+
<ion-icon name="person-outline" />
|
|
47881
|
+
</div>
|
|
47882
|
+
<div class="result-card__body">
|
|
47883
|
+
<span class="result-card__name">{{ user.name || user.handle }}</span>
|
|
47884
|
+
@if (user.handle) {
|
|
47885
|
+
<span class="result-card__handle">@{{ user.handle }}</span>
|
|
47886
|
+
}
|
|
47887
|
+
</div>
|
|
47888
|
+
<div class="result-card__check">
|
|
47889
|
+
@if (isSelected(user.userId)) {
|
|
47890
|
+
<ion-icon name="checkmark-circle-outline" class="check-on" />
|
|
47891
|
+
} @else {
|
|
47892
|
+
<div class="check-off"></div>
|
|
47893
|
+
}
|
|
47894
|
+
</div>
|
|
47895
|
+
</div>
|
|
47896
|
+
}
|
|
47897
|
+
</div>
|
|
47898
|
+
}
|
|
47899
|
+
|
|
47900
|
+
@if (selectedUsers().length > 0) {
|
|
47901
|
+
<div class="selected-section">
|
|
47902
|
+
<span class="selected-section__label">{{ t('selectedLabel') }} ({{ selectedUsers().length }})</span>
|
|
47903
|
+
<div class="selected-chips">
|
|
47904
|
+
@for (user of selectedUsers(); track user.userId) {
|
|
47905
|
+
<div class="selected-chip">
|
|
47906
|
+
<span>{{ user.handle ? '@' + user.handle : user.name || user.userId }}</span>
|
|
47907
|
+
<button class="selected-chip__remove" (click)="toggleUser(user)" aria-label="Quitar">×</button>
|
|
47908
|
+
</div>
|
|
47909
|
+
}
|
|
47910
|
+
</div>
|
|
47911
|
+
<val-button [props]="sendSelectedProps()" (click)="onSendSelected()" />
|
|
47912
|
+
</div>
|
|
47913
|
+
}
|
|
47914
|
+
</div>
|
|
47915
|
+
</ion-content>
|
|
47916
|
+
`, styles: ["ion-content{--padding-bottom: 24px}val-display{margin-bottom:4px;display:block}val-title{margin-bottom:8px;display:block}.role-select-wrap{margin-bottom:12px}.role-select{width:100%}val-searchbar{display:block;margin-bottom:4px}.search-section{display:flex;flex-direction:column;gap:14px}.search-state{display:flex;align-items:center;gap:10px;padding:12px 0;color:var(--ion-color-medium);font-size:.88rem}.email-invite-card{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:12px;border:1.5px solid var(--ion-color-primary);background:color-mix(in srgb,var(--ion-color-primary) 8%,transparent)}.email-icon{font-size:24px;color:var(--ion-color-primary);flex-shrink:0}.email-invite-text{display:flex;flex-direction:column;gap:2px}.email-invite-label{font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.email-invite-address{font-weight:600;font-size:.95rem;color:var(--ion-color-dark);word-break:break-all}.results-list{display:flex;flex-direction:column;gap:8px}.result-card{display:flex;align-items:center;gap:14px;padding:12px 14px;border-radius:12px;background:var(--ion-color-light, #f4f5f8);cursor:pointer;transition:opacity .15s}.result-card:active{opacity:.7}:host-context(body.dark) .result-card,:host-context(html.ion-palette-dark) .result-card,:host-context([data-theme=\"dark\"]) .result-card{background:#ffffff0d}.result-card__avatar{width:40px;height:40px;border-radius:50%;background:color-mix(in srgb,var(--ion-color-primary) 15%,transparent);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--ion-color-primary);flex-shrink:0}.result-card__body{display:flex;flex-direction:column;gap:2px}.result-card__name{font-weight:600;font-size:.9rem;color:var(--ion-color-dark)}.result-card__handle{font-size:.78rem;color:var(--ion-color-medium)}.result-card--selected{border:1.5px solid var(--ion-color-primary);background:color-mix(in srgb,var(--ion-color-primary) 8%,transparent)}.result-card__check{flex-shrink:0;margin-left:auto}.check-on{font-size:22px;color:var(--ion-color-primary)}.check-off{width:22px;height:22px;border-radius:50%;border:2px solid var(--ion-color-medium)}.selected-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08));padding-top:14px;display:flex;flex-direction:column;gap:10px}.selected-section__label{font-size:.78rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.selected-chips{display:flex;flex-wrap:wrap;gap:6px}.selected-chip{display:flex;align-items:center;gap:4px;padding:4px 10px 4px 12px;border-radius:20px;background:color-mix(in srgb,var(--ion-color-primary) 12%,transparent);color:var(--ion-color-primary);font-size:.82rem;font-weight:600}.selected-chip__remove{border:none;background:none;cursor:pointer;font-size:1rem;line-height:1;color:var(--ion-color-primary);padding:0 2px;opacity:.7}.selected-chip__remove:hover{opacity:1}\n"] }]
|
|
47917
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
47918
|
+
type: Input
|
|
47919
|
+
}], orgId: [{
|
|
47920
|
+
type: Input
|
|
47921
|
+
}], existingMemberIds: [{
|
|
47922
|
+
type: Input
|
|
47923
|
+
}], onSuccess: [{
|
|
47924
|
+
type: Input
|
|
47925
|
+
}], i18nNamespace: [{
|
|
47926
|
+
type: Input
|
|
47927
|
+
}] } });
|
|
47928
|
+
|
|
47929
|
+
/**
|
|
47930
|
+
* Defaults i18n (es/en) embebidos en `val-member-detail-modal`. Auto-registrados
|
|
47931
|
+
* en el constructor del componente si el consumer no proveyó el namespace
|
|
47932
|
+
* (`Settings.MemberDetail` por default). SOLO incluye las keys que el modal usa.
|
|
47933
|
+
*/
|
|
47934
|
+
const MEMBER_DETAIL_MODAL_I18N = {
|
|
47935
|
+
es: {
|
|
47936
|
+
close: 'Cerrar',
|
|
47937
|
+
subtitleSelf: 'Tú',
|
|
47938
|
+
roleLabel: 'Rol',
|
|
47939
|
+
roleHint: 'Cambia el rol de este miembro en la organización.',
|
|
47940
|
+
roleReadonly: 'Rol en la organización',
|
|
47941
|
+
roleViewer: 'Visor',
|
|
47942
|
+
roleEditor: 'Editor',
|
|
47943
|
+
roleAdmin: 'Admin',
|
|
47944
|
+
roleSuperAdmin: 'Super Admin',
|
|
47945
|
+
removeCta: 'Quitar de la organización',
|
|
47946
|
+
removeConfirmTitle: 'Quitar miembro',
|
|
47947
|
+
removeConfirmMessage: '¿Quitar a este miembro de la organización?',
|
|
47948
|
+
removeConfirmOk: 'Quitar',
|
|
47949
|
+
cancelCta: 'Cancelar',
|
|
47950
|
+
changeRoleSuccess: 'Rol actualizado.',
|
|
47951
|
+
changeRoleError: 'No se pudo cambiar el rol.',
|
|
47952
|
+
removeSuccess: 'Miembro eliminado.',
|
|
47953
|
+
removeError: 'No se pudo eliminar al miembro.',
|
|
47954
|
+
permissionsTitle: 'Permisos del rol',
|
|
47955
|
+
permAll: 'Todo',
|
|
47956
|
+
permUsers: 'Usuarios',
|
|
47957
|
+
permDocuments: 'Documentos',
|
|
47958
|
+
permRoles: 'Roles',
|
|
47959
|
+
permMedia: 'Media',
|
|
47960
|
+
permTemplates: 'Plantillas',
|
|
47961
|
+
permRead: 'Leer',
|
|
47962
|
+
permWrite: 'Escribir',
|
|
47963
|
+
permCreate: 'Crear',
|
|
47964
|
+
permDelete: 'Eliminar',
|
|
47965
|
+
permManage: 'Gestionar',
|
|
47966
|
+
},
|
|
47967
|
+
en: {
|
|
47968
|
+
close: 'Close',
|
|
47969
|
+
subtitleSelf: 'You',
|
|
47970
|
+
roleLabel: 'Role',
|
|
47971
|
+
roleHint: "Change this member's role in the organization.",
|
|
47972
|
+
roleReadonly: 'Role in the organization',
|
|
47973
|
+
roleViewer: 'Viewer',
|
|
47974
|
+
roleEditor: 'Editor',
|
|
47975
|
+
roleAdmin: 'Admin',
|
|
47976
|
+
roleSuperAdmin: 'Super Admin',
|
|
47977
|
+
removeCta: 'Remove from organization',
|
|
47978
|
+
removeConfirmTitle: 'Remove member',
|
|
47979
|
+
removeConfirmMessage: 'Remove this member from the organization?',
|
|
47980
|
+
removeConfirmOk: 'Remove',
|
|
47981
|
+
cancelCta: 'Cancel',
|
|
47982
|
+
changeRoleSuccess: 'Role updated.',
|
|
47983
|
+
changeRoleError: 'Could not change role.',
|
|
47984
|
+
removeSuccess: 'Member removed.',
|
|
47985
|
+
removeError: 'Could not remove member.',
|
|
47986
|
+
permissionsTitle: 'Role permissions',
|
|
47987
|
+
permAll: 'All',
|
|
47988
|
+
permUsers: 'Users',
|
|
47989
|
+
permDocuments: 'Documents',
|
|
47990
|
+
permRoles: 'Roles',
|
|
47991
|
+
permMedia: 'Media',
|
|
47992
|
+
permTemplates: 'Templates',
|
|
47993
|
+
permRead: 'Read',
|
|
47994
|
+
permWrite: 'Write',
|
|
47995
|
+
permCreate: 'Create',
|
|
47996
|
+
permDelete: 'Delete',
|
|
47997
|
+
permManage: 'Manage',
|
|
47998
|
+
},
|
|
47999
|
+
};
|
|
48000
|
+
|
|
48001
|
+
const DEFAULT_NAMESPACE$2 = 'Settings.MemberDetail';
|
|
48002
|
+
/**
|
|
48003
|
+
* `val-member-detail-modal` — detalle de miembro de organización: perfil, rol y
|
|
48004
|
+
* permisos. Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
48005
|
+
*
|
|
48006
|
+
* Si `canManage` es true, permite cambiar el rol (vía `OrgService.changeMemberRole`)
|
|
48007
|
+
* y quitar al miembro (vía `OrgService.removeMember`, con confirmación destructiva).
|
|
48008
|
+
* Los permisos del rol actual se muestran cuando el consumer los provee en
|
|
48009
|
+
* `availableRoles`.
|
|
48010
|
+
*
|
|
48011
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
48012
|
+
* `onChanged`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar texto en
|
|
48013
|
+
* `slot=end`, identidad en el body con `val-user-avatar`/`val-display`/`val-title`.
|
|
48014
|
+
*
|
|
48015
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
48016
|
+
* `Settings.MemberDetail`.
|
|
48017
|
+
*/
|
|
48018
|
+
class MemberDetailModalComponent {
|
|
48019
|
+
constructor() {
|
|
48020
|
+
this.orgService = inject(OrgService);
|
|
48021
|
+
this.toast = inject(ToastService);
|
|
48022
|
+
this.errors = inject(ValtechErrorService);
|
|
48023
|
+
this.i18n = inject(I18nService);
|
|
48024
|
+
this.confirmDialog = inject(ConfirmationDialogService);
|
|
48025
|
+
/** Organización a la que pertenece el miembro. */
|
|
48026
|
+
this.orgId = '';
|
|
48027
|
+
/** Si true, habilita cambio de rol y eliminación. */
|
|
48028
|
+
this.canManage = false;
|
|
48029
|
+
/** Si true, el miembro mostrado es el propio usuario. */
|
|
48030
|
+
this.isSelf = false;
|
|
48031
|
+
/** Roles disponibles (con permisos opcionales) para el selector de rol. */
|
|
48032
|
+
this.availableRoles = [
|
|
48033
|
+
{ id: 'viewer', name: 'viewer' },
|
|
48034
|
+
{ id: 'editor', name: 'editor' },
|
|
48035
|
+
{ id: 'admin', name: 'admin' },
|
|
48036
|
+
];
|
|
48037
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48038
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$2;
|
|
48039
|
+
this.working = signal(false);
|
|
48040
|
+
this.currentRole = signal('');
|
|
48041
|
+
this.roleControl = new FormControl('');
|
|
48042
|
+
this.displayName = computed(() => this.member?.name || this.member?.handle || this.member?.email || '—');
|
|
48043
|
+
this.subtitle = computed(() => {
|
|
48044
|
+
if (this.isSelf)
|
|
48045
|
+
return this.t('subtitleSelf');
|
|
48046
|
+
if (this.member?.handle)
|
|
48047
|
+
return '@' + this.member.handle;
|
|
48048
|
+
return this.member?.email ?? '';
|
|
48049
|
+
});
|
|
48050
|
+
this.currentRoleLabel = computed(() => this.roleLabel(this.currentRole()));
|
|
48051
|
+
this.permissionsForCurrentRole = computed(() => {
|
|
48052
|
+
const roleId = this.currentRole();
|
|
48053
|
+
const role = this.availableRoles.find(r => r.id === roleId || r.name === roleId);
|
|
48054
|
+
return role?.permissions ?? [];
|
|
48055
|
+
});
|
|
48056
|
+
this.roleSelectProps = computed(() => ({
|
|
48057
|
+
control: this.roleControl,
|
|
48058
|
+
label: '',
|
|
48059
|
+
placeholder: this.t('roleLabel'),
|
|
48060
|
+
type: InputType.SELECT,
|
|
48061
|
+
state: this.working() ? ComponentStates.DISABLED : ComponentStates.ENABLED,
|
|
48062
|
+
options: this.availableRoles.map(r => ({
|
|
48063
|
+
id: r.id,
|
|
48064
|
+
name: this.roleLabel(r.name),
|
|
48065
|
+
order: 0,
|
|
48066
|
+
})),
|
|
48067
|
+
}));
|
|
48068
|
+
this.removeButtonProps = computed(() => ({
|
|
48069
|
+
text: this.t('removeCta'),
|
|
48070
|
+
token: 'member-remove',
|
|
48071
|
+
color: 'danger',
|
|
48072
|
+
fill: 'outline',
|
|
48073
|
+
expand: 'block',
|
|
48074
|
+
size: 'default',
|
|
48075
|
+
type: 'button',
|
|
48076
|
+
state: this.working() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48077
|
+
}));
|
|
48078
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$2)) {
|
|
48079
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$2, MEMBER_DETAIL_MODAL_I18N);
|
|
48080
|
+
}
|
|
48081
|
+
}
|
|
48082
|
+
ngOnInit() {
|
|
48083
|
+
if (!this.i18n.hasNamespace(this.i18nNamespace)) {
|
|
48084
|
+
this.i18n.registerContent(this.i18nNamespace, MEMBER_DETAIL_MODAL_I18N);
|
|
48085
|
+
}
|
|
48086
|
+
const roleName = this.member?.roles?.[0] ?? '';
|
|
48087
|
+
// Resolve the role name to its UUID -- the select uses r.id (UUID) as value
|
|
48088
|
+
const matched = this.availableRoles.find(r => r.name === roleName);
|
|
48089
|
+
const roleId = matched?.id ?? roleName;
|
|
48090
|
+
this.currentRole.set(roleId);
|
|
48091
|
+
this.roleControl.setValue(roleId, { emitEvent: false });
|
|
48092
|
+
this.roleSub = this.roleControl.valueChanges.subscribe(v => {
|
|
48093
|
+
if (v && v !== this.currentRole())
|
|
48094
|
+
void this.onChangeRole(v);
|
|
48095
|
+
});
|
|
48096
|
+
}
|
|
48097
|
+
permissionLabel(perm) {
|
|
48098
|
+
if (perm === '*:*')
|
|
48099
|
+
return this.t('permAll');
|
|
48100
|
+
const [resource, action] = perm.split(':');
|
|
48101
|
+
const resKey = {
|
|
48102
|
+
users: 'permUsers',
|
|
48103
|
+
documents: 'permDocuments',
|
|
48104
|
+
roles: 'permRoles',
|
|
48105
|
+
media: 'permMedia',
|
|
48106
|
+
templates: 'permTemplates',
|
|
48107
|
+
'*': 'permAll',
|
|
48108
|
+
};
|
|
48109
|
+
const actKey = {
|
|
48110
|
+
read: 'permRead',
|
|
48111
|
+
write: 'permWrite',
|
|
48112
|
+
create: 'permCreate',
|
|
48113
|
+
delete: 'permDelete',
|
|
48114
|
+
manage: 'permManage',
|
|
48115
|
+
'*': 'permAll',
|
|
48116
|
+
};
|
|
48117
|
+
const res = this.t(resKey[resource] ?? resource);
|
|
48118
|
+
const act = this.t(actKey[action] ?? action);
|
|
48119
|
+
return `${res}: ${act}`;
|
|
48120
|
+
}
|
|
48121
|
+
async onChangeRole(newRoleId) {
|
|
48122
|
+
if (this.working())
|
|
48123
|
+
return;
|
|
48124
|
+
this.working.set(true);
|
|
48125
|
+
try {
|
|
48126
|
+
await firstValueFrom(this.orgService.changeMemberRole(this.orgId, this.member.userId, newRoleId));
|
|
48127
|
+
this.currentRole.set(newRoleId);
|
|
48128
|
+
this.member = { ...this.member, roles: [newRoleId] };
|
|
48129
|
+
this.toast.show({
|
|
48130
|
+
message: this.t('changeRoleSuccess'),
|
|
48131
|
+
color: 'dark',
|
|
48132
|
+
duration: 3000,
|
|
48133
|
+
});
|
|
48134
|
+
this.onChanged?.();
|
|
48135
|
+
}
|
|
48136
|
+
catch (err) {
|
|
48137
|
+
this.roleControl.setValue(this.currentRole(), { emitEvent: false });
|
|
48138
|
+
this.errors.handle(err, {
|
|
48139
|
+
context: 'memberDetail.changeRole',
|
|
48140
|
+
fallbackKey: 'changeRoleError',
|
|
48141
|
+
i18nNamespace: this.i18nNamespace,
|
|
48142
|
+
});
|
|
48143
|
+
}
|
|
48144
|
+
finally {
|
|
48145
|
+
this.working.set(false);
|
|
48146
|
+
}
|
|
48147
|
+
}
|
|
48148
|
+
async onRemove() {
|
|
48149
|
+
if (this.working())
|
|
48150
|
+
return;
|
|
48151
|
+
const result = await this.confirmDialog.confirmDestructive({
|
|
48152
|
+
title: this.t('removeConfirmTitle'),
|
|
48153
|
+
message: this.t('removeConfirmMessage'),
|
|
48154
|
+
confirmButton: { text: this.t('removeConfirmOk') },
|
|
48155
|
+
cancelButton: { text: this.t('cancelCta') },
|
|
48156
|
+
});
|
|
48157
|
+
if (!result.confirmed)
|
|
48158
|
+
return;
|
|
48159
|
+
this.working.set(true);
|
|
48160
|
+
try {
|
|
48161
|
+
await firstValueFrom(this.orgService.removeMember(this.orgId, this.member.userId));
|
|
48162
|
+
this.toast.show({
|
|
48163
|
+
message: this.t('removeSuccess'),
|
|
48164
|
+
color: 'dark',
|
|
48165
|
+
duration: 3000,
|
|
48166
|
+
});
|
|
48167
|
+
this.onChanged?.();
|
|
48168
|
+
this.dismiss();
|
|
48169
|
+
}
|
|
48170
|
+
catch (err) {
|
|
48171
|
+
this.errors.handle(err, {
|
|
48172
|
+
context: 'memberDetail.remove',
|
|
48173
|
+
fallbackKey: 'removeError',
|
|
48174
|
+
i18nNamespace: this.i18nNamespace,
|
|
48175
|
+
});
|
|
48176
|
+
}
|
|
48177
|
+
finally {
|
|
48178
|
+
this.working.set(false);
|
|
48179
|
+
}
|
|
48180
|
+
}
|
|
48181
|
+
roleLabel(roleIdOrName) {
|
|
48182
|
+
// Try to find by id first (post-change, UUID stored), then by name (initial load)
|
|
48183
|
+
const found = this.availableRoles.find(r => r.id === roleIdOrName || r.name === roleIdOrName);
|
|
48184
|
+
const name = found?.name ?? roleIdOrName;
|
|
48185
|
+
const keyMap = {
|
|
48186
|
+
viewer: 'roleViewer',
|
|
48187
|
+
editor: 'roleEditor',
|
|
48188
|
+
admin: 'roleAdmin',
|
|
48189
|
+
super_admin: 'roleSuperAdmin',
|
|
48190
|
+
};
|
|
48191
|
+
const key = keyMap[name] ?? name;
|
|
48192
|
+
const label = this.t(key);
|
|
48193
|
+
return label && !label.startsWith('[') ? label : name;
|
|
48194
|
+
}
|
|
48195
|
+
ngOnDestroy() {
|
|
48196
|
+
this.roleSub?.unsubscribe();
|
|
48197
|
+
}
|
|
48198
|
+
dismiss() {
|
|
48199
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
48200
|
+
}
|
|
48201
|
+
t(key) {
|
|
48202
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
48203
|
+
}
|
|
48204
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MemberDetailModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
48205
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MemberDetailModalComponent, isStandalone: true, selector: "val-member-detail-modal", inputs: { _modalRef: "_modalRef", member: "member", orgId: "orgId", canManage: "canManage", isSelf: "isSelf", availableRoles: "availableRoles", onChanged: "onChanged", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
48206
|
+
<ion-header>
|
|
48207
|
+
<ion-toolbar>
|
|
48208
|
+
<ion-buttons slot="end">
|
|
48209
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48210
|
+
<strong>{{ t('close') }}</strong>
|
|
48211
|
+
</ion-button>
|
|
48212
|
+
</ion-buttons>
|
|
48213
|
+
</ion-toolbar>
|
|
48214
|
+
</ion-header>
|
|
48215
|
+
|
|
48216
|
+
<ion-content class="ion-padding">
|
|
48217
|
+
<div class="member-head">
|
|
48218
|
+
<val-user-avatar
|
|
48219
|
+
[props]="{
|
|
48220
|
+
name: member.name,
|
|
48221
|
+
avatarUrl: member.avatar,
|
|
48222
|
+
email: member.email,
|
|
48223
|
+
size: 'large',
|
|
48224
|
+
}"
|
|
48225
|
+
/>
|
|
48226
|
+
<val-display [props]="{ content: displayName(), size: 'small', color: 'dark' }" />
|
|
48227
|
+
<val-title
|
|
48228
|
+
[props]="{
|
|
48229
|
+
content: subtitle(),
|
|
48230
|
+
size: 'large',
|
|
48231
|
+
color: '',
|
|
48232
|
+
bold: false,
|
|
48233
|
+
}"
|
|
48234
|
+
/>
|
|
48235
|
+
</div>
|
|
48236
|
+
|
|
48237
|
+
<div class="role-section">
|
|
48238
|
+
@if (canManage) {
|
|
48239
|
+
<val-title
|
|
48240
|
+
[props]="{
|
|
48241
|
+
content: t('roleLabel'),
|
|
48242
|
+
size: 'small',
|
|
48243
|
+
color: 'dark',
|
|
48244
|
+
bold: false,
|
|
48245
|
+
}"
|
|
48246
|
+
/>
|
|
48247
|
+
<val-select-input data-testid="member-role-select" [props]="roleSelectProps()" />
|
|
48248
|
+
<val-text
|
|
48249
|
+
[props]="{
|
|
48250
|
+
content: t('roleHint'),
|
|
48251
|
+
size: 'small',
|
|
48252
|
+
color: 'medium',
|
|
48253
|
+
bold: false,
|
|
48254
|
+
}"
|
|
48255
|
+
/>
|
|
48256
|
+
} @else {
|
|
48257
|
+
<span class="role-readonly-label">{{ t('roleReadonly') }}</span>
|
|
48258
|
+
<span class="member-role-badge">{{ currentRoleLabel() }}</span>
|
|
48259
|
+
}
|
|
48260
|
+
</div>
|
|
48261
|
+
|
|
48262
|
+
@if (permissionsForCurrentRole().length > 0) {
|
|
48263
|
+
<div class="perms-section">
|
|
48264
|
+
<span class="perms-label">{{ t('permissionsTitle') }}</span>
|
|
48265
|
+
<div class="perms-list">
|
|
48266
|
+
@for (perm of permissionsForCurrentRole(); track perm) {
|
|
48267
|
+
<span class="perm-chip">{{ permissionLabel(perm) }}</span>
|
|
48268
|
+
}
|
|
48269
|
+
</div>
|
|
48270
|
+
</div>
|
|
48271
|
+
}
|
|
48272
|
+
|
|
48273
|
+
@if (canManage) {
|
|
48274
|
+
<div class="remove-section">
|
|
48275
|
+
<val-button [props]="removeButtonProps()" (click)="onRemove()" />
|
|
48276
|
+
</div>
|
|
48277
|
+
}
|
|
48278
|
+
</ion-content>
|
|
48279
|
+
`, isInline: true, styles: ["ion-content{--padding-bottom: 24px}.member-head{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;margin-bottom:20px}val-display{display:block}val-title{display:block}.role-section{display:flex;flex-direction:column;gap:8px;margin-bottom:24px}.role-readonly-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.member-role-badge{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:4px 12px;border-radius:20px;width:fit-content;background:color-mix(in srgb,var(--ion-color-primary) 12%,transparent);color:var(--ion-color-primary)}.perms-section{display:flex;flex-direction:column;gap:10px;margin-bottom:24px}.perms-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.perms-list{display:flex;flex-wrap:wrap;gap:6px}.perm-chip{font-size:.75rem;font-weight:500;padding:3px 10px;border-radius:20px;border:1px solid var(--val-border-color, rgba(0, 0, 0, .12));color:var(--ion-color-dark);background:transparent}.remove-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08));padding-top:20px}\n"], dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: SearchSelectorComponent, selector: "val-select-input", inputs: ["preset", "props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: UserAvatarComponent, selector: "val-user-avatar", inputs: ["props"], outputs: ["onClick"] }] }); }
|
|
48280
|
+
}
|
|
48281
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MemberDetailModalComponent, decorators: [{
|
|
48282
|
+
type: Component,
|
|
48283
|
+
args: [{ selector: 'val-member-detail-modal', standalone: true, imports: [
|
|
48284
|
+
IonHeader,
|
|
48285
|
+
IonToolbar,
|
|
48286
|
+
IonButtons,
|
|
48287
|
+
IonButton,
|
|
48288
|
+
IonContent,
|
|
48289
|
+
ReactiveFormsModule,
|
|
48290
|
+
ButtonComponent,
|
|
48291
|
+
DisplayComponent,
|
|
48292
|
+
SearchSelectorComponent,
|
|
48293
|
+
TextComponent,
|
|
48294
|
+
TitleComponent,
|
|
48295
|
+
UserAvatarComponent,
|
|
48296
|
+
], template: `
|
|
48297
|
+
<ion-header>
|
|
48298
|
+
<ion-toolbar>
|
|
48299
|
+
<ion-buttons slot="end">
|
|
48300
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48301
|
+
<strong>{{ t('close') }}</strong>
|
|
48302
|
+
</ion-button>
|
|
48303
|
+
</ion-buttons>
|
|
48304
|
+
</ion-toolbar>
|
|
48305
|
+
</ion-header>
|
|
48306
|
+
|
|
48307
|
+
<ion-content class="ion-padding">
|
|
48308
|
+
<div class="member-head">
|
|
48309
|
+
<val-user-avatar
|
|
48310
|
+
[props]="{
|
|
48311
|
+
name: member.name,
|
|
48312
|
+
avatarUrl: member.avatar,
|
|
48313
|
+
email: member.email,
|
|
48314
|
+
size: 'large',
|
|
48315
|
+
}"
|
|
48316
|
+
/>
|
|
48317
|
+
<val-display [props]="{ content: displayName(), size: 'small', color: 'dark' }" />
|
|
48318
|
+
<val-title
|
|
48319
|
+
[props]="{
|
|
48320
|
+
content: subtitle(),
|
|
48321
|
+
size: 'large',
|
|
48322
|
+
color: '',
|
|
48323
|
+
bold: false,
|
|
48324
|
+
}"
|
|
48325
|
+
/>
|
|
48326
|
+
</div>
|
|
48327
|
+
|
|
48328
|
+
<div class="role-section">
|
|
48329
|
+
@if (canManage) {
|
|
48330
|
+
<val-title
|
|
48331
|
+
[props]="{
|
|
48332
|
+
content: t('roleLabel'),
|
|
48333
|
+
size: 'small',
|
|
48334
|
+
color: 'dark',
|
|
48335
|
+
bold: false,
|
|
48336
|
+
}"
|
|
48337
|
+
/>
|
|
48338
|
+
<val-select-input data-testid="member-role-select" [props]="roleSelectProps()" />
|
|
48339
|
+
<val-text
|
|
48340
|
+
[props]="{
|
|
48341
|
+
content: t('roleHint'),
|
|
48342
|
+
size: 'small',
|
|
48343
|
+
color: 'medium',
|
|
48344
|
+
bold: false,
|
|
48345
|
+
}"
|
|
48346
|
+
/>
|
|
48347
|
+
} @else {
|
|
48348
|
+
<span class="role-readonly-label">{{ t('roleReadonly') }}</span>
|
|
48349
|
+
<span class="member-role-badge">{{ currentRoleLabel() }}</span>
|
|
48350
|
+
}
|
|
48351
|
+
</div>
|
|
48352
|
+
|
|
48353
|
+
@if (permissionsForCurrentRole().length > 0) {
|
|
48354
|
+
<div class="perms-section">
|
|
48355
|
+
<span class="perms-label">{{ t('permissionsTitle') }}</span>
|
|
48356
|
+
<div class="perms-list">
|
|
48357
|
+
@for (perm of permissionsForCurrentRole(); track perm) {
|
|
48358
|
+
<span class="perm-chip">{{ permissionLabel(perm) }}</span>
|
|
48359
|
+
}
|
|
48360
|
+
</div>
|
|
48361
|
+
</div>
|
|
48362
|
+
}
|
|
48363
|
+
|
|
48364
|
+
@if (canManage) {
|
|
48365
|
+
<div class="remove-section">
|
|
48366
|
+
<val-button [props]="removeButtonProps()" (click)="onRemove()" />
|
|
48367
|
+
</div>
|
|
48368
|
+
}
|
|
48369
|
+
</ion-content>
|
|
48370
|
+
`, styles: ["ion-content{--padding-bottom: 24px}.member-head{display:flex;flex-direction:column;align-items:center;text-align:center;gap:6px;margin-bottom:20px}val-display{display:block}val-title{display:block}.role-section{display:flex;flex-direction:column;gap:8px;margin-bottom:24px}.role-readonly-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.member-role-badge{font-size:.78rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:4px 12px;border-radius:20px;width:fit-content;background:color-mix(in srgb,var(--ion-color-primary) 12%,transparent);color:var(--ion-color-primary)}.perms-section{display:flex;flex-direction:column;gap:10px;margin-bottom:24px}.perms-label{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--ion-color-medium)}.perms-list{display:flex;flex-wrap:wrap;gap:6px}.perm-chip{font-size:.75rem;font-weight:500;padding:3px 10px;border-radius:20px;border:1px solid var(--val-border-color, rgba(0, 0, 0, .12));color:var(--ion-color-dark);background:transparent}.remove-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08));padding-top:20px}\n"] }]
|
|
48371
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
48372
|
+
type: Input
|
|
48373
|
+
}], member: [{
|
|
48374
|
+
type: Input
|
|
48375
|
+
}], orgId: [{
|
|
48376
|
+
type: Input
|
|
48377
|
+
}], canManage: [{
|
|
48378
|
+
type: Input
|
|
48379
|
+
}], isSelf: [{
|
|
48380
|
+
type: Input
|
|
48381
|
+
}], availableRoles: [{
|
|
48382
|
+
type: Input
|
|
48383
|
+
}], onChanged: [{
|
|
48384
|
+
type: Input
|
|
48385
|
+
}], i18nNamespace: [{
|
|
48386
|
+
type: Input
|
|
48387
|
+
}] } });
|
|
48388
|
+
|
|
48389
|
+
/**
|
|
48390
|
+
* Defaults i18n (es/en) embebidos en `val-edit-org-modal`. Auto-registrados en
|
|
48391
|
+
* el constructor del componente si el consumer no proveyó el namespace
|
|
48392
|
+
* (`EditOrgModal` por default). SOLO incluye las keys que el modal usa.
|
|
48393
|
+
*/
|
|
48394
|
+
const EDIT_ORG_MODAL_I18N = {
|
|
48395
|
+
es: {
|
|
48396
|
+
title: 'Editar organización',
|
|
48397
|
+
subtitle: 'Actualiza el nombre y descripción.',
|
|
48398
|
+
nameLabel: 'Nombre',
|
|
48399
|
+
namePlaceholder: 'Nombre de la organización',
|
|
48400
|
+
nameRequired: 'El nombre es obligatorio.',
|
|
48401
|
+
nameMin: 'Mínimo 2 caracteres.',
|
|
48402
|
+
descriptionLabel: 'Descripción (opcional)',
|
|
48403
|
+
descriptionPlaceholder: 'Describe tu organización',
|
|
48404
|
+
saveCta: 'Guardar cambios',
|
|
48405
|
+
close: 'Cancelar',
|
|
48406
|
+
saveSuccess: 'Organización actualizada.',
|
|
48407
|
+
saveError: 'No se pudo guardar. Intenta de nuevo.',
|
|
48408
|
+
fillRequired: 'Completa todos los campos requeridos.',
|
|
48409
|
+
},
|
|
48410
|
+
en: {
|
|
48411
|
+
title: 'Edit organization',
|
|
48412
|
+
subtitle: 'Update the name and description.',
|
|
48413
|
+
nameLabel: 'Name',
|
|
48414
|
+
namePlaceholder: 'Organization name',
|
|
48415
|
+
nameRequired: 'Name is required.',
|
|
48416
|
+
nameMin: 'Minimum 2 characters.',
|
|
48417
|
+
descriptionLabel: 'Description (optional)',
|
|
48418
|
+
descriptionPlaceholder: 'Describe your organization',
|
|
48419
|
+
saveCta: 'Save changes',
|
|
48420
|
+
close: 'Cancel',
|
|
48421
|
+
saveSuccess: 'Organization updated.',
|
|
48422
|
+
saveError: 'Could not save. Please try again.',
|
|
48423
|
+
fillRequired: 'Please fill in all required fields.',
|
|
48424
|
+
},
|
|
48425
|
+
};
|
|
48426
|
+
|
|
48427
|
+
const DEFAULT_NAMESPACE$1 = 'EditOrgModal';
|
|
48428
|
+
/**
|
|
48429
|
+
* `val-edit-org-modal` — modal de edición de organización (nombre + descripción).
|
|
48430
|
+
* Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por la vista de
|
|
48431
|
+
* gestión de organización (y futuras vistas org-aware).
|
|
48432
|
+
*
|
|
48433
|
+
* Edita la org vía `OrgService.updateOrg`. El formulario se construye una vez y se
|
|
48434
|
+
* mantiene reactivo a idioma + estado de trabajo vía effects `allowSignalWrites`.
|
|
48435
|
+
* Si el consumer no pasa `org`, cae al `activeOrgId` del `AuthService`.
|
|
48436
|
+
*
|
|
48437
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
48438
|
+
* `onSuccess(updated)`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar
|
|
48439
|
+
* texto en `slot=end`, título/subtítulo en el body con `val-display`/`val-title`.
|
|
48440
|
+
*
|
|
48441
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
48442
|
+
* `EditOrgModal`.
|
|
48443
|
+
*/
|
|
48444
|
+
class EditOrgModalComponent {
|
|
48445
|
+
constructor() {
|
|
48446
|
+
this.i18n = inject(I18nService);
|
|
48447
|
+
this.orgService = inject(OrgService);
|
|
48448
|
+
this.toast = inject(ToastService);
|
|
48449
|
+
this.errors = inject(ValtechErrorService);
|
|
48450
|
+
this.auth = inject(AuthService);
|
|
48451
|
+
/** Organización a editar (pasada por `componentProps`). */
|
|
48452
|
+
this.org = null;
|
|
48453
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48454
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$1;
|
|
48455
|
+
this.saving = signal(false);
|
|
48456
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$1)) {
|
|
48457
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$1, EDIT_ORG_MODAL_I18N);
|
|
48458
|
+
}
|
|
48459
|
+
this.formMeta = signal(this.buildFormMeta());
|
|
48460
|
+
effect(() => {
|
|
48461
|
+
this.i18n.lang();
|
|
48462
|
+
this.formMeta.set(this.buildFormMeta());
|
|
48463
|
+
}, { allowSignalWrites: true });
|
|
48464
|
+
effect(() => {
|
|
48465
|
+
const w = this.saving();
|
|
48466
|
+
this.formMeta.update(m => ({
|
|
48467
|
+
...m,
|
|
48468
|
+
state: w ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48469
|
+
actions: {
|
|
48470
|
+
...m.actions,
|
|
48471
|
+
state: w ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48472
|
+
},
|
|
48473
|
+
}));
|
|
48474
|
+
}, { allowSignalWrites: true });
|
|
48475
|
+
}
|
|
48476
|
+
ngOnInit() {
|
|
48477
|
+
this.formMeta.set(this.buildFormMeta());
|
|
48478
|
+
}
|
|
48479
|
+
get activeOrgId() {
|
|
48480
|
+
const u = this.auth.user();
|
|
48481
|
+
return u?.activeOrgId ?? u?.activeOrg ?? '';
|
|
48482
|
+
}
|
|
48483
|
+
buildFormMeta() {
|
|
48484
|
+
const nameField = {
|
|
48485
|
+
token: 'edit-org-name',
|
|
48486
|
+
name: 'name',
|
|
48487
|
+
label: this.t('nameLabel'),
|
|
48488
|
+
hint: '',
|
|
48489
|
+
placeholder: this.t('namePlaceholder'),
|
|
48490
|
+
type: InputType.TEXT,
|
|
48491
|
+
order: 1,
|
|
48492
|
+
validators: [Validators.required, Validators.minLength(2), Validators.maxLength(100)],
|
|
48493
|
+
errors: {
|
|
48494
|
+
required: this.t('nameRequired'),
|
|
48495
|
+
minlength: this.t('nameMin'),
|
|
48496
|
+
},
|
|
48497
|
+
value: this.org?.name ?? '',
|
|
48498
|
+
state: ComponentStates.ENABLED,
|
|
48499
|
+
};
|
|
48500
|
+
const descField = {
|
|
48501
|
+
token: 'edit-org-desc',
|
|
48502
|
+
name: 'description',
|
|
48503
|
+
label: this.t('descriptionLabel'),
|
|
48504
|
+
hint: '',
|
|
48505
|
+
placeholder: this.t('descriptionPlaceholder'),
|
|
48506
|
+
type: InputType.TEXTAREA,
|
|
48507
|
+
order: 2,
|
|
48508
|
+
validators: [],
|
|
48509
|
+
errors: {},
|
|
48510
|
+
value: this.org?.description ?? '',
|
|
48511
|
+
state: ComponentStates.ENABLED,
|
|
48512
|
+
};
|
|
48513
|
+
return {
|
|
48514
|
+
name: '',
|
|
48515
|
+
state: ComponentStates.ENABLED,
|
|
48516
|
+
sections: [{ name: '', order: 1, fields: [nameField, descField] }],
|
|
48517
|
+
actions: {
|
|
48518
|
+
text: this.t('saveCta'),
|
|
48519
|
+
color: 'dark',
|
|
48520
|
+
type: 'submit',
|
|
48521
|
+
fill: 'solid',
|
|
48522
|
+
size: 'default',
|
|
48523
|
+
shape: 'round',
|
|
48524
|
+
expand: 'block',
|
|
48525
|
+
state: ComponentStates.ENABLED,
|
|
48526
|
+
token: 'edit-org-submit',
|
|
48527
|
+
},
|
|
48528
|
+
};
|
|
48529
|
+
}
|
|
48530
|
+
onFormSubmit(event) {
|
|
48531
|
+
const name = event.fields['name'];
|
|
48532
|
+
if (!name?.trim()) {
|
|
48533
|
+
this.toast.show({
|
|
48534
|
+
message: this.t('fillRequired'),
|
|
48535
|
+
duration: 3000,
|
|
48536
|
+
color: 'dark',
|
|
48537
|
+
position: 'top',
|
|
48538
|
+
});
|
|
48539
|
+
return;
|
|
48540
|
+
}
|
|
48541
|
+
const description = event.fields['description'] ?? '';
|
|
48542
|
+
void this.save(name, description);
|
|
48543
|
+
}
|
|
48544
|
+
async save(name, description) {
|
|
48545
|
+
const orgId = this.org?.id ?? this.activeOrgId;
|
|
48546
|
+
if (!orgId || this.saving())
|
|
48547
|
+
return;
|
|
48548
|
+
this.saving.set(true);
|
|
48549
|
+
try {
|
|
48550
|
+
const updated = await firstValueFrom(this.orgService.updateOrg(orgId, { name, description }));
|
|
48551
|
+
this.toast.show({
|
|
48552
|
+
message: this.t('saveSuccess'),
|
|
48553
|
+
color: 'dark',
|
|
48554
|
+
duration: 3500,
|
|
48555
|
+
});
|
|
48556
|
+
this.onSuccess?.(updated);
|
|
48557
|
+
this._modalRef?.dismiss(updated, 'confirm');
|
|
48558
|
+
}
|
|
48559
|
+
catch (err) {
|
|
48560
|
+
this.errors.handle(err, {
|
|
48561
|
+
context: 'editOrgModal.save',
|
|
48562
|
+
fallbackKey: 'saveError',
|
|
48563
|
+
i18nNamespace: this.i18nNamespace,
|
|
48564
|
+
});
|
|
48565
|
+
}
|
|
48566
|
+
finally {
|
|
48567
|
+
this.saving.set(false);
|
|
48568
|
+
}
|
|
48569
|
+
}
|
|
48570
|
+
dismiss() {
|
|
48571
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
48572
|
+
}
|
|
48573
|
+
t(key) {
|
|
48574
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
48575
|
+
}
|
|
48576
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditOrgModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
48577
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: EditOrgModalComponent, isStandalone: true, selector: "val-edit-org-modal", inputs: { _modalRef: "_modalRef", org: "org", onSuccess: "onSuccess", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
48578
|
+
<ion-header>
|
|
48579
|
+
<ion-toolbar>
|
|
48580
|
+
<ion-buttons slot="end">
|
|
48581
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48582
|
+
<strong>{{ t('close') }}</strong>
|
|
48583
|
+
</ion-button>
|
|
48584
|
+
</ion-buttons>
|
|
48585
|
+
</ion-toolbar>
|
|
48586
|
+
</ion-header>
|
|
48587
|
+
<ion-content class="ion-padding">
|
|
48588
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
48589
|
+
<val-title
|
|
48590
|
+
[props]="{
|
|
48591
|
+
content: t('subtitle'),
|
|
48592
|
+
size: 'large',
|
|
48593
|
+
color: '',
|
|
48594
|
+
bold: false,
|
|
48595
|
+
}"
|
|
48596
|
+
/>
|
|
48597
|
+
<val-form [props]="formMeta()" (onSubmit)="onFormSubmit($event)" />
|
|
48598
|
+
</ion-content>
|
|
48599
|
+
`, isInline: true, dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }] }); }
|
|
48600
|
+
}
|
|
48601
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: EditOrgModalComponent, decorators: [{
|
|
48602
|
+
type: Component,
|
|
48603
|
+
args: [{
|
|
48604
|
+
selector: 'val-edit-org-modal',
|
|
48605
|
+
standalone: true,
|
|
48606
|
+
imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, FormComponent, DisplayComponent, TitleComponent],
|
|
48607
|
+
template: `
|
|
48608
|
+
<ion-header>
|
|
48609
|
+
<ion-toolbar>
|
|
48610
|
+
<ion-buttons slot="end">
|
|
48611
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48612
|
+
<strong>{{ t('close') }}</strong>
|
|
48613
|
+
</ion-button>
|
|
48614
|
+
</ion-buttons>
|
|
48615
|
+
</ion-toolbar>
|
|
48616
|
+
</ion-header>
|
|
48617
|
+
<ion-content class="ion-padding">
|
|
48618
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
48619
|
+
<val-title
|
|
48620
|
+
[props]="{
|
|
48621
|
+
content: t('subtitle'),
|
|
48622
|
+
size: 'large',
|
|
48623
|
+
color: '',
|
|
48624
|
+
bold: false,
|
|
48625
|
+
}"
|
|
48626
|
+
/>
|
|
48627
|
+
<val-form [props]="formMeta()" (onSubmit)="onFormSubmit($event)" />
|
|
48628
|
+
</ion-content>
|
|
48629
|
+
`,
|
|
48630
|
+
}]
|
|
48631
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
48632
|
+
type: Input
|
|
48633
|
+
}], org: [{
|
|
48634
|
+
type: Input
|
|
48635
|
+
}], onSuccess: [{
|
|
48636
|
+
type: Input
|
|
48637
|
+
}], i18nNamespace: [{
|
|
48638
|
+
type: Input
|
|
48639
|
+
}] } });
|
|
48640
|
+
|
|
48641
|
+
/**
|
|
48642
|
+
* Defaults i18n (es/en) embebidos en `val-transfer-ownership-modal`.
|
|
48643
|
+
* Auto-registrados en el constructor del componente si el consumer no proveyó el
|
|
48644
|
+
* namespace (`Settings.TransferModal` por default). SOLO incluye las keys que el
|
|
48645
|
+
* modal usa.
|
|
48646
|
+
*/
|
|
48647
|
+
const TRANSFER_OWNERSHIP_MODAL_I18N = {
|
|
48648
|
+
es: {
|
|
48649
|
+
title: 'Transferir propiedad',
|
|
48650
|
+
hint: 'Selecciona el nuevo propietario de la organización.',
|
|
48651
|
+
searchPlaceholder: 'Buscar miembro...',
|
|
48652
|
+
empty: 'No hay otros miembros disponibles.',
|
|
48653
|
+
noResults: 'Sin resultados para',
|
|
48654
|
+
confirmCta: 'Confirmar transferencia',
|
|
48655
|
+
close: 'Cancelar',
|
|
48656
|
+
},
|
|
48657
|
+
en: {
|
|
48658
|
+
title: 'Transfer ownership',
|
|
48659
|
+
hint: 'Select the new owner of the organization.',
|
|
48660
|
+
searchPlaceholder: 'Search member...',
|
|
48661
|
+
empty: 'No other members available.',
|
|
48662
|
+
noResults: 'No results for',
|
|
48663
|
+
confirmCta: 'Confirm transfer',
|
|
48664
|
+
close: 'Cancel',
|
|
48665
|
+
},
|
|
48666
|
+
};
|
|
48667
|
+
|
|
48668
|
+
const DEFAULT_NAMESPACE = 'Settings.TransferModal';
|
|
48669
|
+
/**
|
|
48670
|
+
* `val-transfer-ownership-modal` — selector de miembro para transferir la
|
|
48671
|
+
* propiedad de la organización. Promovido desde `showcase` bajo el proceso de
|
|
48672
|
+
* ADR-021.
|
|
48673
|
+
*
|
|
48674
|
+
* Recibe la lista de candidatos por `members` (todos excepto el owner actual),
|
|
48675
|
+
* permite filtrarlos con `val-searchbar` y, al confirmar, ejecuta el callback
|
|
48676
|
+
* `onConfirm(newOwnerId)`. La ejecución real de la transferencia (vía
|
|
48677
|
+
* `OrgService.transferOwnership`) queda en el consumer.
|
|
48678
|
+
*
|
|
48679
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps`. Header
|
|
48680
|
+
* canónico (Regla #5): sin `ion-title`, botón Cerrar texto en `slot=end`,
|
|
48681
|
+
* título/subtítulo en el body con `val-display`/`val-title`.
|
|
48682
|
+
*
|
|
48683
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
48684
|
+
* `Settings.TransferModal`.
|
|
48685
|
+
*/
|
|
48686
|
+
class TransferOwnershipModalComponent {
|
|
48687
|
+
constructor() {
|
|
48688
|
+
this.i18n = inject(I18nService);
|
|
48689
|
+
/** Lista de miembros transferibles (todos excepto el owner actual). */
|
|
48690
|
+
this.members = [];
|
|
48691
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48692
|
+
this.i18nNamespace = DEFAULT_NAMESPACE;
|
|
48693
|
+
this.query = signal('');
|
|
48694
|
+
this.selectedId = signal('');
|
|
48695
|
+
this.filtered = computed(() => {
|
|
48696
|
+
const q = this.query().trim().toLowerCase();
|
|
48697
|
+
if (!q)
|
|
48698
|
+
return this.members;
|
|
48699
|
+
return this.members.filter(m => m.name?.toLowerCase().includes(q) ||
|
|
48700
|
+
m.email?.toLowerCase().includes(q) ||
|
|
48701
|
+
m.userId.toLowerCase().includes(q));
|
|
48702
|
+
});
|
|
48703
|
+
this.noResultsLabel = computed(() => `${this.t('noResults')} "${this.query()}"`);
|
|
48704
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE)) {
|
|
48705
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48706
|
+
}
|
|
48707
|
+
}
|
|
48708
|
+
ngOnInit() {
|
|
48709
|
+
if (!this.i18n.hasNamespace(this.i18nNamespace)) {
|
|
48710
|
+
this.i18n.registerContent(this.i18nNamespace, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48711
|
+
}
|
|
48712
|
+
}
|
|
48713
|
+
confirm() {
|
|
48714
|
+
const id = this.selectedId();
|
|
48715
|
+
if (!id)
|
|
48716
|
+
return;
|
|
48717
|
+
this.onConfirm?.(id);
|
|
48718
|
+
this.dismiss();
|
|
48719
|
+
}
|
|
48720
|
+
dismiss() {
|
|
48721
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
48722
|
+
}
|
|
48723
|
+
t(key) {
|
|
48724
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
48725
|
+
}
|
|
48726
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TransferOwnershipModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
48727
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: TransferOwnershipModalComponent, isStandalone: true, selector: "val-transfer-ownership-modal", inputs: { members: "members", onConfirm: "onConfirm", _modalRef: "_modalRef", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
48728
|
+
<ion-header>
|
|
48729
|
+
<ion-toolbar>
|
|
48730
|
+
<ion-buttons slot="end">
|
|
48731
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48732
|
+
<strong>{{ t('close') }}</strong>
|
|
48733
|
+
</ion-button>
|
|
48734
|
+
</ion-buttons>
|
|
48735
|
+
</ion-toolbar>
|
|
48736
|
+
</ion-header>
|
|
48737
|
+
|
|
48738
|
+
<ion-content class="ion-padding">
|
|
48739
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
48740
|
+
<val-title
|
|
48741
|
+
[props]="{
|
|
48742
|
+
content: t('hint'),
|
|
48743
|
+
size: 'large',
|
|
48744
|
+
color: '',
|
|
48745
|
+
bold: false,
|
|
48746
|
+
}"
|
|
48747
|
+
/>
|
|
48748
|
+
|
|
48749
|
+
<val-searchbar
|
|
48750
|
+
[props]="{ placeholder: t('searchPlaceholder'), debounce: 150 }"
|
|
48751
|
+
(filterEvent)="query.set($event)"
|
|
48752
|
+
/>
|
|
48753
|
+
|
|
48754
|
+
@if (members.length === 0) {
|
|
48755
|
+
<val-text
|
|
48756
|
+
[props]="{
|
|
48757
|
+
content: t('empty'),
|
|
48758
|
+
size: 'medium',
|
|
48759
|
+
color: 'medium',
|
|
48760
|
+
bold: false,
|
|
48761
|
+
}"
|
|
48762
|
+
/>
|
|
48763
|
+
} @else if (filtered().length === 0) {
|
|
48764
|
+
<val-text
|
|
48765
|
+
[props]="{
|
|
48766
|
+
content: noResultsLabel(),
|
|
48767
|
+
size: 'medium',
|
|
48768
|
+
color: 'medium',
|
|
48769
|
+
bold: false,
|
|
48770
|
+
}"
|
|
48771
|
+
/>
|
|
48772
|
+
} @else {
|
|
48773
|
+
<div class="transfer-member-list">
|
|
48774
|
+
@for (m of filtered(); track m.userId) {
|
|
48775
|
+
<button
|
|
48776
|
+
class="transfer-member-row"
|
|
48777
|
+
[class.transfer-member-row--selected]="selectedId() === m.userId"
|
|
48778
|
+
(click)="selectedId.set(m.userId)"
|
|
48779
|
+
type="button"
|
|
48780
|
+
>
|
|
48781
|
+
<span class="transfer-member-name">{{ m.name || m.email || m.userId }}</span>
|
|
48782
|
+
@if (selectedId() === m.userId) {
|
|
48783
|
+
<span class="transfer-member-check">✓</span>
|
|
48784
|
+
}
|
|
48785
|
+
</button>
|
|
48786
|
+
}
|
|
48787
|
+
</div>
|
|
48788
|
+
}
|
|
48789
|
+
|
|
48790
|
+
<div class="transfer-confirm-row">
|
|
48791
|
+
<ion-button expand="block" color="dark" [disabled]="!selectedId()" (click)="confirm()">
|
|
48792
|
+
{{ t('confirmCta') }}
|
|
48793
|
+
</ion-button>
|
|
48794
|
+
</div>
|
|
48795
|
+
</ion-content>
|
|
48796
|
+
`, isInline: true, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:16px}val-searchbar{display:block;margin-bottom:12px}.transfer-member-list{display:flex;flex-direction:column;gap:4px}.transfer-member-row{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-radius:10px;border:1.5px solid var(--ion-color-light);background:transparent;cursor:pointer;width:100%;text-align:left;font-size:15px;color:var(--ion-color-dark);transition:border-color .15s}.transfer-member-row--selected{border-color:var(--ion-color-dark);background:var(--ion-color-light)}.transfer-member-check{font-size:17px;color:var(--ion-color-dark)}.transfer-confirm-row{margin-top:24px}\n"], dependencies: [{ kind: "component", type: IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: SearchbarComponent, selector: "val-searchbar", inputs: ["preset", "props"], outputs: ["filterEvent", "focusEvent", "blurEvent"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }] }); }
|
|
48797
|
+
}
|
|
48798
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TransferOwnershipModalComponent, decorators: [{
|
|
48799
|
+
type: Component,
|
|
48800
|
+
args: [{ selector: 'val-transfer-ownership-modal', standalone: true, imports: [
|
|
48801
|
+
IonHeader,
|
|
48802
|
+
IonToolbar,
|
|
48803
|
+
IonButtons,
|
|
48804
|
+
IonButton,
|
|
48805
|
+
IonContent,
|
|
48806
|
+
SearchbarComponent,
|
|
48807
|
+
DisplayComponent,
|
|
48808
|
+
TextComponent,
|
|
48809
|
+
TitleComponent,
|
|
48810
|
+
], template: `
|
|
48811
|
+
<ion-header>
|
|
48812
|
+
<ion-toolbar>
|
|
48813
|
+
<ion-buttons slot="end">
|
|
48814
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
48815
|
+
<strong>{{ t('close') }}</strong>
|
|
48816
|
+
</ion-button>
|
|
48817
|
+
</ion-buttons>
|
|
48818
|
+
</ion-toolbar>
|
|
48819
|
+
</ion-header>
|
|
48820
|
+
|
|
48821
|
+
<ion-content class="ion-padding">
|
|
48822
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
48823
|
+
<val-title
|
|
48824
|
+
[props]="{
|
|
48825
|
+
content: t('hint'),
|
|
48826
|
+
size: 'large',
|
|
48827
|
+
color: '',
|
|
48828
|
+
bold: false,
|
|
48829
|
+
}"
|
|
48830
|
+
/>
|
|
48831
|
+
|
|
48832
|
+
<val-searchbar
|
|
48833
|
+
[props]="{ placeholder: t('searchPlaceholder'), debounce: 150 }"
|
|
48834
|
+
(filterEvent)="query.set($event)"
|
|
48835
|
+
/>
|
|
48836
|
+
|
|
48837
|
+
@if (members.length === 0) {
|
|
48838
|
+
<val-text
|
|
48839
|
+
[props]="{
|
|
48840
|
+
content: t('empty'),
|
|
48841
|
+
size: 'medium',
|
|
48842
|
+
color: 'medium',
|
|
48843
|
+
bold: false,
|
|
48844
|
+
}"
|
|
48845
|
+
/>
|
|
48846
|
+
} @else if (filtered().length === 0) {
|
|
48847
|
+
<val-text
|
|
48848
|
+
[props]="{
|
|
48849
|
+
content: noResultsLabel(),
|
|
48850
|
+
size: 'medium',
|
|
48851
|
+
color: 'medium',
|
|
48852
|
+
bold: false,
|
|
48853
|
+
}"
|
|
48854
|
+
/>
|
|
48855
|
+
} @else {
|
|
48856
|
+
<div class="transfer-member-list">
|
|
48857
|
+
@for (m of filtered(); track m.userId) {
|
|
48858
|
+
<button
|
|
48859
|
+
class="transfer-member-row"
|
|
48860
|
+
[class.transfer-member-row--selected]="selectedId() === m.userId"
|
|
48861
|
+
(click)="selectedId.set(m.userId)"
|
|
48862
|
+
type="button"
|
|
48863
|
+
>
|
|
48864
|
+
<span class="transfer-member-name">{{ m.name || m.email || m.userId }}</span>
|
|
48865
|
+
@if (selectedId() === m.userId) {
|
|
48866
|
+
<span class="transfer-member-check">✓</span>
|
|
48867
|
+
}
|
|
48868
|
+
</button>
|
|
48869
|
+
}
|
|
48870
|
+
</div>
|
|
48871
|
+
}
|
|
48872
|
+
|
|
48873
|
+
<div class="transfer-confirm-row">
|
|
48874
|
+
<ion-button expand="block" color="dark" [disabled]="!selectedId()" (click)="confirm()">
|
|
48875
|
+
{{ t('confirmCta') }}
|
|
48876
|
+
</ion-button>
|
|
48877
|
+
</div>
|
|
48878
|
+
</ion-content>
|
|
48879
|
+
`, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:16px}val-searchbar{display:block;margin-bottom:12px}.transfer-member-list{display:flex;flex-direction:column;gap:4px}.transfer-member-row{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-radius:10px;border:1.5px solid var(--ion-color-light);background:transparent;cursor:pointer;width:100%;text-align:left;font-size:15px;color:var(--ion-color-dark);transition:border-color .15s}.transfer-member-row--selected{border-color:var(--ion-color-dark);background:var(--ion-color-light)}.transfer-member-check{font-size:17px;color:var(--ion-color-dark)}.transfer-confirm-row{margin-top:24px}\n"] }]
|
|
48880
|
+
}], ctorParameters: () => [], propDecorators: { members: [{
|
|
48881
|
+
type: Input
|
|
48882
|
+
}], onConfirm: [{
|
|
48883
|
+
type: Input
|
|
48884
|
+
}], _modalRef: [{
|
|
48885
|
+
type: Input
|
|
48886
|
+
}], i18nNamespace: [{
|
|
48887
|
+
type: Input
|
|
48888
|
+
}] } });
|
|
48889
|
+
|
|
47377
48890
|
/** Built-in label sets for the three platform locales. */
|
|
47378
48891
|
const CALLOUT_LABELS = {
|
|
47379
48892
|
es: {
|
|
@@ -57698,5 +59211,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
57698
59211
|
* Generated bundle index. Do not edit.
|
|
57699
59212
|
*/
|
|
57700
59213
|
|
|
57701
|
-
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
59214
|
+
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationsService, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OutlineDefault, OutlineDefaultBlock, OutlineDefaultFull, OutlineDefaultRound, OutlineDefaultRoundBlock, OutlineDefaultRoundFull, PATTERN_MOTIFS, PATTERN_PALETTES, PATTERN_STYLE_CONFIGS, PLATFORM_CONFIGS, PageContentComponent, PageLinksComponent, PageRefreshService, PageTemplateComponent, PageWavesComponent, PageWrapperComponent, PaginationComponent, PaginationService, PasswordInputComponent, PatternComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
57702
59215
|
//# sourceMappingURL=valtech-components.mjs.map
|