valtech-components 2.0.985 → 2.0.986
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/molecules/date-input/date-input.component.mjs +97 -14
- package/esm2022/lib/components/organisms/account-view/account-view.component.mjs +732 -0
- package/esm2022/lib/components/organisms/account-view/account-view.i18n.mjs +96 -0
- package/esm2022/lib/components/organisms/account-view/account.routes.mjs +29 -0
- package/esm2022/lib/components/organisms/account-view/types.mjs +2 -0
- package/esm2022/lib/components/organisms/create-org-modal/create-org-modal.component.mjs +240 -0
- package/esm2022/lib/components/organisms/create-org-modal/create-org-modal.i18n.mjs +46 -0
- package/esm2022/lib/components/organisms/delete-account-modal/delete-account-modal.component.mjs +272 -0
- package/esm2022/lib/components/organisms/delete-account-modal/delete-account-modal.i18n.mjs +40 -0
- package/esm2022/lib/components/organisms/org-info-sheet/org-info-sheet.component.mjs +205 -0
- package/esm2022/lib/components/organisms/org-info-sheet/org-info-sheet.i18n.mjs +35 -0
- package/esm2022/lib/components/organisms/switch-org-modal/switch-org-modal.component.mjs +280 -0
- package/esm2022/lib/components/organisms/switch-org-modal/switch-org-modal.i18n.mjs +26 -0
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +8 -1
- package/fesm2022/valtech-components.mjs +2275 -277
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/molecules/date-input/date-input.component.d.ts +9 -0
- package/lib/components/organisms/account-view/account-view.component.d.ts +88 -0
- package/lib/components/organisms/account-view/account-view.i18n.d.ts +7 -0
- package/lib/components/organisms/account-view/account.routes.d.ts +24 -0
- package/lib/components/organisms/account-view/types.d.ts +44 -0
- package/lib/components/organisms/create-org-modal/create-org-modal.component.d.ts +45 -0
- package/lib/components/organisms/create-org-modal/create-org-modal.i18n.d.ts +7 -0
- package/lib/components/organisms/delete-account-modal/delete-account-modal.component.d.ts +50 -0
- package/lib/components/organisms/delete-account-modal/delete-account-modal.i18n.d.ts +7 -0
- package/lib/components/organisms/org-info-sheet/org-info-sheet.component.d.ts +44 -0
- package/lib/components/organisms/org-info-sheet/org-info-sheet.i18n.d.ts +12 -0
- package/lib/components/organisms/switch-org-modal/switch-org-modal.component.d.ts +47 -0
- package/lib/components/organisms/switch-org-modal/switch-org-modal.i18n.d.ts +7 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +7 -0
|
@@ -7,7 +7,7 @@ import { provideHttpClient, withInterceptors, HttpClient, HttpErrorResponse } fr
|
|
|
7
7
|
import * as i1$1 from '@angular/fire/firestore';
|
|
8
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';
|
|
9
9
|
import * as i1$5 from '@angular/common';
|
|
10
|
-
import { isPlatformBrowser, CommonModule, NgStyle, NgFor, DOCUMENT, NgClass } from '@angular/common';
|
|
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';
|
|
12
12
|
import { provideFirebaseApp, initializeApp } from '@angular/fire/app';
|
|
13
13
|
import * as i1 from '@angular/fire/auth';
|
|
@@ -23,9 +23,9 @@ import { IonicModule, ToastController, NavController } from '@ionic/angular';
|
|
|
23
23
|
import { isSupported, getMessaging as getMessaging$1 } from 'firebase/messaging';
|
|
24
24
|
import { getApps, getApp, initializeApp as initializeApp$1 } from 'firebase/app';
|
|
25
25
|
import * as i2$1 from '@ionic/angular/standalone';
|
|
26
|
-
import { AlertController, IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime,
|
|
26
|
+
import { AlertController, IonAvatar, IonCard, IonIcon, IonButton, IonSpinner, IonText, IonModal, IonHeader, IonToolbar, IonContent, IonButtons, IonTitle, IonProgressBar, IonSkeletonText, IonFab, IonFabButton, IonFabList, IonLabel, IonCardContent, IonCardHeader, IonCardTitle, IonCardSubtitle, IonCheckbox, IonTextarea, IonDatetime, IonInput, IonSelect, IonSelectOption, IonPopover, IonList, IonItem, IonRadioGroup, IonRadio, IonRange, IonSearchbar, IonSegment, IonSegmentButton, IonToggle, IonRippleEffect, IonAccordion, IonAccordionGroup, IonTabBar, IonTabButton, IonBadge, IonBreadcrumb, IonBreadcrumbs, IonChip, IonNote, IonDatetimeButton, ToastController as ToastController$1, IonCol, IonRow, IonRefresher, IonRefresherContent, IonMenuButton, IonFooter, IonListHeader, IonInfiniteScroll, IonInfiniteScrollContent, IonGrid, MenuController, IonMenu, IonMenuToggle, IonSplitPane } from '@ionic/angular/standalone';
|
|
27
27
|
import { addIcons } from 'ionicons';
|
|
28
|
-
import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, menuOutline } from 'ionicons/icons';
|
|
28
|
+
import { addOutline, addCircleOutline, alertOutline, alertCircleOutline, arrowBackOutline, arrowForwardOutline, arrowDownOutline, settings, settingsOutline, checkmarkCircleOutline, ellipsisHorizontalOutline, notifications, notificationsOutline, openOutline, closeOutline, chatbubblesOutline, shareOutline, heart, heartOutline, home, homeOutline, eyeOffOutline, eyeOutline, scanOutline, chevronDownOutline, chevronForwardOutline, checkmarkOutline, clipboardOutline, copyOutline, filterOutline, locationOutline, calendarOutline, businessOutline, logoTwitter, logoInstagram, logoLinkedin, logoYoutube, logoTiktok, logoFacebook, logoGoogle, createOutline, trashOutline, playOutline, peopleOutline, phonePortraitOutline, refreshOutline, documentTextOutline, lockClosedOutline, informationCircleOutline, logoNpm, removeOutline, optionsOutline, personOutline, shieldCheckmarkOutline, keyOutline, desktopOutline, logOutOutline, cloudDownloadOutline, cloudOutline, gitBranchOutline, layersOutline, serverOutline, warningOutline, bulbOutline, lockOpenOutline, diamondOutline, add, close, share, create, trash, star, camera, mic, send, downloadOutline, chevronDown, language, globeOutline, checkmark, list, grid, apps, menu, search, person, helpCircle, informationCircle, documentText, mail, calendar, folder, chevronForward, ellipsisHorizontal, chevronBack, playBack, playForward, ellipse, starOutline, starHalf, heartHalf, checkmarkCircle, timeOutline, flag, trendingUp, trendingDown, remove, analytics, people, cash, cart, eye, chatbubbleOutline, thumbsUpOutline, thumbsUp, happyOutline, happy, sadOutline, sad, chevronUp, pin, pencil, callOutline, logoWhatsapp, paperPlaneOutline, mailOutline, chevronDownCircleOutline, closeCircle, alertCircle, logoApple, logoMicrosoft, linkOutline, unlinkOutline, cloudOfflineOutline, documentOutline, attachOutline, cameraOutline, closeCircleOutline, imageOutline, chevronBackOutline, sendOutline, chatbubbleEllipsesOutline, swapVerticalOutline, chevronUpOutline, searchOutline, cartOutline, chatbubble, compass, compassOutline, gridOutline, listOutline, folderOutline, documents, documentsOutline, statsChart, statsChartOutline, laptopOutline, swapHorizontalOutline, menuOutline } from 'ionicons/icons';
|
|
29
29
|
import { Browser } from '@capacitor/browser';
|
|
30
30
|
import * as i1$6 from '@angular/platform-browser';
|
|
31
31
|
import { DomSanitizer, Meta, Title } from '@angular/platform-browser';
|
|
@@ -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.986';
|
|
58
58
|
|
|
59
59
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
60
60
|
let isRefreshing = false;
|
|
@@ -15796,11 +15796,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
15796
15796
|
type: Input
|
|
15797
15797
|
}] } });
|
|
15798
15798
|
|
|
15799
|
+
const DATE_INPUT_I18N = {
|
|
15800
|
+
es: { selectDate: 'Seleccionar fecha', selectTime: 'Seleccionar hora' },
|
|
15801
|
+
en: { selectDate: 'Select date', selectTime: 'Select time' },
|
|
15802
|
+
};
|
|
15799
15803
|
/**
|
|
15800
15804
|
* val-date-input
|
|
15801
15805
|
*
|
|
15802
15806
|
* A date picker input integrated with Angular forms, using Ionic's datetime component.
|
|
15803
15807
|
*
|
|
15808
|
+
* Cuando el control no tiene valor, muestra un botón con el texto `placeholder`
|
|
15809
|
+
* (o un default i18n "Seleccionar fecha") en vez de renderizar en blanco —
|
|
15810
|
+
* `ion-datetime-button` no soporta placeholder, por eso usamos un trigger propio.
|
|
15811
|
+
*
|
|
15804
15812
|
* @example
|
|
15805
15813
|
* <val-date-input [props]="{ control: myControl, hint: 'Select a date' }"></val-date-input>
|
|
15806
15814
|
*
|
|
@@ -15821,6 +15829,10 @@ class DateInputComponent {
|
|
|
15821
15829
|
* Resolved props after merging preset + explicit props.
|
|
15822
15830
|
*/
|
|
15823
15831
|
this.resolvedProps = {};
|
|
15832
|
+
// Auto-registro de defaults i18n (anti key-faltante → anti storm de CD).
|
|
15833
|
+
if (!this.i18n.hasNamespace('DateInput')) {
|
|
15834
|
+
this.i18n.registerContent('DateInput', DATE_INPUT_I18N);
|
|
15835
|
+
}
|
|
15824
15836
|
}
|
|
15825
15837
|
/** Done button text - from props or i18n default */
|
|
15826
15838
|
get doneText() {
|
|
@@ -15830,6 +15842,52 @@ class DateInputComponent {
|
|
|
15830
15842
|
get cancelText() {
|
|
15831
15843
|
return this.resolvedProps?.cancelText || this.i18n.t('cancel');
|
|
15832
15844
|
}
|
|
15845
|
+
/** Presentación del datetime (default: date). */
|
|
15846
|
+
get presentation() {
|
|
15847
|
+
return this.resolvedProps?.presentation || 'date';
|
|
15848
|
+
}
|
|
15849
|
+
/** Texto del trigger cuando NO hay valor (placeholder explícito o default i18n). */
|
|
15850
|
+
get placeholderText() {
|
|
15851
|
+
if (this.resolvedProps?.placeholder)
|
|
15852
|
+
return this.resolvedProps.placeholder;
|
|
15853
|
+
this.i18n.lang(); // reactividad ante cambio de idioma
|
|
15854
|
+
return this.presentation === 'time'
|
|
15855
|
+
? this.i18n.t('selectTime', 'DateInput')
|
|
15856
|
+
: this.i18n.t('selectDate', 'DateInput');
|
|
15857
|
+
}
|
|
15858
|
+
/** Id del trigger/datetime — estable; se garantiza no vacío en resolveProps. */
|
|
15859
|
+
get triggerId() {
|
|
15860
|
+
return this.resolvedProps?.token || '';
|
|
15861
|
+
}
|
|
15862
|
+
/** Valor formateado del control para mostrar en el trigger ('' si vacío). */
|
|
15863
|
+
get displayValue() {
|
|
15864
|
+
const raw = this.resolvedProps?.control?.value;
|
|
15865
|
+
if (!raw)
|
|
15866
|
+
return '';
|
|
15867
|
+
const d = new Date(raw);
|
|
15868
|
+
if (isNaN(d.getTime()))
|
|
15869
|
+
return String(raw);
|
|
15870
|
+
this.i18n.lang(); // reactividad
|
|
15871
|
+
const locale = 'es-ES';
|
|
15872
|
+
try {
|
|
15873
|
+
switch (this.presentation) {
|
|
15874
|
+
case 'time':
|
|
15875
|
+
return new Intl.DateTimeFormat(locale, { timeStyle: 'short' }).format(d);
|
|
15876
|
+
case 'month':
|
|
15877
|
+
case 'month-year':
|
|
15878
|
+
return new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(d);
|
|
15879
|
+
case 'year':
|
|
15880
|
+
return new Intl.DateTimeFormat(locale, { year: 'numeric' }).format(d);
|
|
15881
|
+
case 'date-time':
|
|
15882
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: 'medium', timeStyle: 'short' }).format(d);
|
|
15883
|
+
default:
|
|
15884
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: 'medium' }).format(d);
|
|
15885
|
+
}
|
|
15886
|
+
}
|
|
15887
|
+
catch {
|
|
15888
|
+
return String(raw);
|
|
15889
|
+
}
|
|
15890
|
+
}
|
|
15833
15891
|
ngOnInit() {
|
|
15834
15892
|
this.resolveProps();
|
|
15835
15893
|
this.applyDefaultValue();
|
|
@@ -15845,13 +15903,16 @@ class DateInputComponent {
|
|
|
15845
15903
|
* Explicit props take precedence over preset values.
|
|
15846
15904
|
*/
|
|
15847
15905
|
resolveProps() {
|
|
15848
|
-
const presetProps = this.preset
|
|
15849
|
-
? this.presets.get('dateInput', this.preset)
|
|
15850
|
-
: {};
|
|
15906
|
+
const presetProps = this.preset ? this.presets.get('dateInput', this.preset) : {};
|
|
15851
15907
|
this.resolvedProps = {
|
|
15852
15908
|
...presetProps,
|
|
15853
15909
|
...this.props,
|
|
15854
15910
|
};
|
|
15911
|
+
// Garantizar un token (id) no vacío: lo necesitan [trigger] del modal y el
|
|
15912
|
+
// [id] del ion-datetime para vincularse. Si el consumer no lo pasó, generamos uno.
|
|
15913
|
+
if (!this.resolvedProps.token) {
|
|
15914
|
+
this.resolvedProps.token = `val-date-${Math.random().toString(36).slice(2, 10)}`;
|
|
15915
|
+
}
|
|
15855
15916
|
}
|
|
15856
15917
|
applyDefaultValue() {
|
|
15857
15918
|
if (!this.resolvedProps.control)
|
|
@@ -15879,14 +15940,25 @@ class DateInputComponent {
|
|
|
15879
15940
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DateInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
15880
15941
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DateInputComponent, isStandalone: true, selector: "val-date-input", inputs: { preset: "preset", props: "props" }, usesOnChanges: true, ngImport: i0, template: `
|
|
15881
15942
|
<div class="button-container">
|
|
15882
|
-
|
|
15943
|
+
<!-- Trigger propio (reemplaza ion-datetime-button, que renderiza en blanco
|
|
15944
|
+
cuando el control no tiene valor). Muestra el valor formateado o el
|
|
15945
|
+
placeholder, y abre el modal vía [trigger]. -->
|
|
15946
|
+
<ion-button
|
|
15947
|
+
[id]="triggerId"
|
|
15948
|
+
class="action date-trigger"
|
|
15949
|
+
fill="outline"
|
|
15950
|
+
color="medium"
|
|
15951
|
+
[class.is-placeholder]="!displayValue"
|
|
15952
|
+
>
|
|
15953
|
+
{{ displayValue || placeholderText }}
|
|
15954
|
+
</ion-button>
|
|
15883
15955
|
</div>
|
|
15884
|
-
<ion-modal [keepContentsMounted]="true">
|
|
15956
|
+
<ion-modal [trigger]="triggerId" [keepContentsMounted]="true">
|
|
15885
15957
|
<ng-template>
|
|
15886
15958
|
<ion-datetime
|
|
15887
15959
|
[formControl]="resolvedProps.control"
|
|
15888
15960
|
[id]="resolvedProps.token"
|
|
15889
|
-
presentation="
|
|
15961
|
+
[presentation]="presentation"
|
|
15890
15962
|
locale="es-ES"
|
|
15891
15963
|
[firstDayOfWeek]="1"
|
|
15892
15964
|
[showDefaultButtons]="true"
|
|
@@ -15901,20 +15973,31 @@ class DateInputComponent {
|
|
|
15901
15973
|
</ion-datetime>
|
|
15902
15974
|
</ng-template>
|
|
15903
15975
|
</ion-modal>
|
|
15904
|
-
`, 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)}.section{margin-top:1rem}.input{margin:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}.button-container{display:flex;flex-direction:column;align-items:flex-start}.action{margin-top:.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }, { kind: "component", type:
|
|
15976
|
+
`, 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)}.section{margin-top:1rem}.input{margin:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}.button-container{display:flex;flex-direction:column;align-items:flex-start}.action{margin-top:.25rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { 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: IonDatetime, selector: "ion-datetime", inputs: ["cancelText", "clearText", "color", "dayValues", "disabled", "doneText", "firstDayOfWeek", "formatOptions", "highlightedDates", "hourCycle", "hourValues", "isDateEnabled", "locale", "max", "min", "minuteValues", "mode", "monthValues", "multiple", "name", "preferWheel", "presentation", "readonly", "showAdjacentDays", "showClearButton", "showDefaultButtons", "showDefaultTimeLabel", "showDefaultTitle", "size", "titleSelectedDatesFormatter", "value", "yearValues"] }, { kind: "component", type: IonModal, selector: "ion-modal" }] }); }
|
|
15905
15977
|
}
|
|
15906
15978
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DateInputComponent, decorators: [{
|
|
15907
15979
|
type: Component,
|
|
15908
|
-
args: [{ selector: 'val-date-input', standalone: true, imports: [CommonModule, ReactiveFormsModule,
|
|
15980
|
+
args: [{ selector: 'val-date-input', standalone: true, imports: [CommonModule, ReactiveFormsModule, IonButton, IonDatetime, IonModal], template: `
|
|
15909
15981
|
<div class="button-container">
|
|
15910
|
-
|
|
15982
|
+
<!-- Trigger propio (reemplaza ion-datetime-button, que renderiza en blanco
|
|
15983
|
+
cuando el control no tiene valor). Muestra el valor formateado o el
|
|
15984
|
+
placeholder, y abre el modal vía [trigger]. -->
|
|
15985
|
+
<ion-button
|
|
15986
|
+
[id]="triggerId"
|
|
15987
|
+
class="action date-trigger"
|
|
15988
|
+
fill="outline"
|
|
15989
|
+
color="medium"
|
|
15990
|
+
[class.is-placeholder]="!displayValue"
|
|
15991
|
+
>
|
|
15992
|
+
{{ displayValue || placeholderText }}
|
|
15993
|
+
</ion-button>
|
|
15911
15994
|
</div>
|
|
15912
|
-
<ion-modal [keepContentsMounted]="true">
|
|
15995
|
+
<ion-modal [trigger]="triggerId" [keepContentsMounted]="true">
|
|
15913
15996
|
<ng-template>
|
|
15914
15997
|
<ion-datetime
|
|
15915
15998
|
[formControl]="resolvedProps.control"
|
|
15916
15999
|
[id]="resolvedProps.token"
|
|
15917
|
-
presentation="
|
|
16000
|
+
[presentation]="presentation"
|
|
15918
16001
|
locale="es-ES"
|
|
15919
16002
|
[firstDayOfWeek]="1"
|
|
15920
16003
|
[showDefaultButtons]="true"
|
|
@@ -15930,7 +16013,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
15930
16013
|
</ng-template>
|
|
15931
16014
|
</ion-modal>
|
|
15932
16015
|
`, 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)}.section{margin-top:1rem}.input{margin:var(--val-form-field-gap, .5rem) 0}@media (min-width: 768px){.input{margin:var(--val-form-field-gap, .75rem) 0}}.submit-actions--sticky{position:sticky;bottom:0;z-index:1;background:var(--ion-background-color);border-top:1px solid var(--ion-color-step-150, rgba(0, 0, 0, .08));padding:.75rem 0 calc(.75rem + env(safe-area-inset-bottom))}.field-description{display:block;font-size:.75rem;color:var(--ion-color-dark);margin-bottom:.25rem;line-height:1.4}.button-container{display:flex;flex-direction:column;align-items:flex-start}.action{margin-top:.25rem}\n"] }]
|
|
15933
|
-
}], propDecorators: { preset: [{
|
|
16016
|
+
}], ctorParameters: () => [], propDecorators: { preset: [{
|
|
15934
16017
|
type: Input
|
|
15935
16018
|
}], props: [{
|
|
15936
16019
|
type: Input
|
|
@@ -41652,7 +41735,7 @@ const PROFILE_VIEW_I18N = {
|
|
|
41652
41735
|
const HANDLE_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
41653
41736
|
const HANDLE_MIN = 3;
|
|
41654
41737
|
const HANDLE_MAX = 20;
|
|
41655
|
-
const DEFAULT_NAMESPACE$
|
|
41738
|
+
const DEFAULT_NAMESPACE$7 = 'Settings.Profile';
|
|
41656
41739
|
/**
|
|
41657
41740
|
* `val-profile-view` — vista Perfil full-feature autocontenida (organism).
|
|
41658
41741
|
*
|
|
@@ -41702,7 +41785,7 @@ class ProfileViewComponent {
|
|
|
41702
41785
|
showPhone: merged.showPhone ?? true,
|
|
41703
41786
|
showShareCta: merged.showShareCta ?? true,
|
|
41704
41787
|
profileBaseUrl: merged.profileBaseUrl ?? '',
|
|
41705
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
41788
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$7,
|
|
41706
41789
|
onSaved: merged.onSaved,
|
|
41707
41790
|
onAvatarUploaded: merged.onAvatarUploaded,
|
|
41708
41791
|
};
|
|
@@ -42618,7 +42701,7 @@ const PREFERENCES_VIEW_I18N = {
|
|
|
42618
42701
|
},
|
|
42619
42702
|
};
|
|
42620
42703
|
|
|
42621
|
-
const DEFAULT_NAMESPACE$
|
|
42704
|
+
const DEFAULT_NAMESPACE$6 = 'Settings.General';
|
|
42622
42705
|
const DEFAULT_LANGUAGES = ['es', 'en'];
|
|
42623
42706
|
/**
|
|
42624
42707
|
* `val-preferences-view` — vista de preferencias de UI cross-app (tema +
|
|
@@ -42655,7 +42738,7 @@ class PreferencesViewComponent {
|
|
|
42655
42738
|
showLanguage: merged.showLanguage ?? true,
|
|
42656
42739
|
showFontSize: merged.showFontSize ?? true,
|
|
42657
42740
|
supportedLanguages: merged.supportedLanguages ?? DEFAULT_LANGUAGES,
|
|
42658
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
42741
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$6,
|
|
42659
42742
|
onThemeChanged: merged.onThemeChanged,
|
|
42660
42743
|
onLanguageChanged: merged.onLanguageChanged,
|
|
42661
42744
|
onFontSizeChanged: merged.onFontSizeChanged,
|
|
@@ -44467,7 +44550,7 @@ const SECURITY_VIEW_I18N = {
|
|
|
44467
44550
|
};
|
|
44468
44551
|
|
|
44469
44552
|
addIcons({ laptopOutline, phonePortraitOutline });
|
|
44470
|
-
const DEFAULT_NAMESPACE = 'Settings.Security';
|
|
44553
|
+
const DEFAULT_NAMESPACE$5 = 'Settings.Security';
|
|
44471
44554
|
/**
|
|
44472
44555
|
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
44473
44556
|
*
|
|
@@ -44516,7 +44599,7 @@ class SecurityViewComponent {
|
|
|
44516
44599
|
showChangeEmail: merged.showChangeEmail ?? true,
|
|
44517
44600
|
showMfa: merged.showMfa ?? true,
|
|
44518
44601
|
showPolicies: merged.showPolicies ?? true,
|
|
44519
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
44602
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$5,
|
|
44520
44603
|
handleDeepLinks: merged.handleDeepLinks ?? true,
|
|
44521
44604
|
homeRoute: merged.homeRoute ?? '/app/home',
|
|
44522
44605
|
onMfaCompleted: merged.onMfaCompleted,
|
|
@@ -45280,187 +45363,2198 @@ function provideValtechSecurityRoutes(opts) {
|
|
|
45280
45363
|
];
|
|
45281
45364
|
}
|
|
45282
45365
|
|
|
45283
|
-
|
|
45284
|
-
|
|
45366
|
+
class OrgService {
|
|
45367
|
+
constructor(config, http) {
|
|
45368
|
+
this.config = config;
|
|
45369
|
+
this.http = http;
|
|
45370
|
+
}
|
|
45371
|
+
get baseUrl() {
|
|
45372
|
+
return `${this.config.apiUrl}/org`;
|
|
45373
|
+
}
|
|
45374
|
+
listMyOrgs() {
|
|
45375
|
+
return this.http.get(`${this.baseUrl}/my`).pipe(map$1(r => r.organizations));
|
|
45376
|
+
}
|
|
45377
|
+
listMyOrgsPage(params) {
|
|
45378
|
+
const queryParams = new URLSearchParams();
|
|
45379
|
+
if (params?.limit)
|
|
45380
|
+
queryParams.set('limit', String(params.limit));
|
|
45381
|
+
if (params?.nextToken)
|
|
45382
|
+
queryParams.set('nextToken', params.nextToken);
|
|
45383
|
+
const qs = queryParams.toString();
|
|
45384
|
+
const url = `${this.baseUrl}/my${qs ? '?' + qs : ''}`;
|
|
45385
|
+
return this.http.get(url);
|
|
45386
|
+
}
|
|
45387
|
+
getOrg(orgId) {
|
|
45388
|
+
return this.http.get(`${this.baseUrl}/${orgId}`).pipe(map$1(r => r.organization));
|
|
45389
|
+
}
|
|
45390
|
+
createOrg(req) {
|
|
45391
|
+
return this.http.post(`${this.baseUrl}`, req).pipe(map$1(r => r.organization));
|
|
45392
|
+
}
|
|
45393
|
+
updateOrg(orgId, req) {
|
|
45394
|
+
return this.http
|
|
45395
|
+
.put(`${this.baseUrl}/${orgId}`, req)
|
|
45396
|
+
.pipe(map$1(r => r.organization));
|
|
45397
|
+
}
|
|
45398
|
+
deleteOrg(orgId) {
|
|
45399
|
+
return this.http.delete(`${this.baseUrl}/${orgId}`);
|
|
45400
|
+
}
|
|
45401
|
+
inviteUser(orgId, req) {
|
|
45402
|
+
return this.http.post(`${this.baseUrl}/${orgId}/invite`, req);
|
|
45403
|
+
}
|
|
45404
|
+
leaveOrg(orgId) {
|
|
45405
|
+
return this.http.post(`${this.baseUrl}/${orgId}/leave`, {});
|
|
45406
|
+
}
|
|
45407
|
+
getOrgMembers(orgId, params) {
|
|
45408
|
+
const queryParams = new URLSearchParams();
|
|
45409
|
+
if (params?.limit)
|
|
45410
|
+
queryParams.set('limit', String(params.limit));
|
|
45411
|
+
if (params?.nextToken)
|
|
45412
|
+
queryParams.set('nextToken', params.nextToken);
|
|
45413
|
+
const qs = queryParams.toString();
|
|
45414
|
+
const url = `${this.baseUrl}/${orgId}/members${qs ? '?' + qs : ''}`;
|
|
45415
|
+
return this.http.get(url);
|
|
45416
|
+
}
|
|
45417
|
+
listOrgRoles(orgId) {
|
|
45418
|
+
return this.http
|
|
45419
|
+
.get(`${this.baseUrl}/${orgId}/roles`)
|
|
45420
|
+
.pipe(map$1(r => r.roles ?? []));
|
|
45421
|
+
}
|
|
45422
|
+
changeMemberRole(orgId, userId, roleId) {
|
|
45423
|
+
const body = { roleId };
|
|
45424
|
+
return this.http.put(`${this.baseUrl}/${orgId}/members/${userId}/role`, body);
|
|
45425
|
+
}
|
|
45426
|
+
removeMember(orgId, userId) {
|
|
45427
|
+
return this.http.delete(`${this.baseUrl}/${orgId}/members/${userId}`);
|
|
45428
|
+
}
|
|
45429
|
+
transferOwnership(orgId, newOwnerId) {
|
|
45430
|
+
return this.http
|
|
45431
|
+
.post(`${this.baseUrl}/${orgId}/transfer-ownership`, { newOwnerId })
|
|
45432
|
+
.pipe(map$1(r => r.organization));
|
|
45433
|
+
}
|
|
45434
|
+
validateInviteToken(token) {
|
|
45435
|
+
return this.http.post(`${this.config.apiUrl}/v2/actions/validate`, { token });
|
|
45436
|
+
}
|
|
45437
|
+
executeInviteToken(token) {
|
|
45438
|
+
return this.http.post(`${this.config.apiUrl}/v2/actions/execute`, { token });
|
|
45439
|
+
}
|
|
45440
|
+
getPendingInvitations() {
|
|
45441
|
+
return this.http
|
|
45442
|
+
.get(`${this.config.apiUrl}/organizations/invitations/pending`)
|
|
45443
|
+
.pipe(map$1(r => r.items ?? []));
|
|
45444
|
+
}
|
|
45445
|
+
acceptInvitation(orgId) {
|
|
45446
|
+
return this.http.post(`${this.baseUrl}/invitations/${orgId}/accept`, {});
|
|
45447
|
+
}
|
|
45448
|
+
declineInvitation(orgId) {
|
|
45449
|
+
return this.http.post(`${this.baseUrl}/invitations/${orgId}/decline`, {});
|
|
45450
|
+
}
|
|
45451
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: i1$3.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
45452
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgService, providedIn: 'root' }); }
|
|
45453
|
+
}
|
|
45454
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgService, decorators: [{
|
|
45455
|
+
type: Injectable,
|
|
45456
|
+
args: [{ providedIn: 'root' }]
|
|
45457
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
45458
|
+
type: Inject,
|
|
45459
|
+
args: [VALTECH_AUTH_CONFIG]
|
|
45460
|
+
}] }, { type: i1$3.HttpClient }] });
|
|
45461
|
+
|
|
45462
|
+
/**
|
|
45463
|
+
* Defaults i18n (es/en) embebidos en `val-create-org-modal`. Auto-registrados en
|
|
45464
|
+
* el constructor del componente si el consumer no proveyó el namespace
|
|
45465
|
+
* (`CreateOrgModal` por default). SOLO incluye las keys que el modal usa.
|
|
45466
|
+
*/
|
|
45467
|
+
const CREATE_ORG_MODAL_I18N = {
|
|
45285
45468
|
es: {
|
|
45286
|
-
|
|
45287
|
-
|
|
45288
|
-
|
|
45289
|
-
|
|
45290
|
-
|
|
45291
|
-
|
|
45469
|
+
pageTitle: 'Nueva organización',
|
|
45470
|
+
pageDescription: 'Crea una nueva organización',
|
|
45471
|
+
nameLabel: 'Nombre',
|
|
45472
|
+
namePlaceholder: 'Nombre de la organización',
|
|
45473
|
+
typeLabel: 'Tipo',
|
|
45474
|
+
descriptionLabel: 'Descripción',
|
|
45475
|
+
descriptionPlaceholder: 'Opcional',
|
|
45476
|
+
createCta: 'Crear organización',
|
|
45477
|
+
close: 'Cancelar',
|
|
45478
|
+
nameRequired: 'El nombre es obligatorio',
|
|
45479
|
+
nameMin: 'Mínimo 2 caracteres',
|
|
45480
|
+
typePersonal: 'Personal',
|
|
45481
|
+
typePrivate: 'Privada',
|
|
45482
|
+
typePublic: 'Pública',
|
|
45483
|
+
typeBusiness: 'Empresa',
|
|
45484
|
+
successMsg: 'Organización creada. Cambiando...',
|
|
45485
|
+
fillRequired: 'Completa todos los campos requeridos.',
|
|
45292
45486
|
},
|
|
45293
45487
|
en: {
|
|
45294
|
-
|
|
45295
|
-
|
|
45296
|
-
|
|
45297
|
-
|
|
45298
|
-
|
|
45299
|
-
|
|
45300
|
-
|
|
45301
|
-
|
|
45302
|
-
|
|
45303
|
-
|
|
45304
|
-
|
|
45305
|
-
|
|
45306
|
-
|
|
45307
|
-
|
|
45488
|
+
pageTitle: 'New organization',
|
|
45489
|
+
pageDescription: 'Create a new organization',
|
|
45490
|
+
nameLabel: 'Name',
|
|
45491
|
+
namePlaceholder: 'Organization name',
|
|
45492
|
+
typeLabel: 'Type',
|
|
45493
|
+
descriptionLabel: 'Description',
|
|
45494
|
+
descriptionPlaceholder: 'Optional',
|
|
45495
|
+
createCta: 'Create organization',
|
|
45496
|
+
close: 'Cancel',
|
|
45497
|
+
nameRequired: 'Name is required',
|
|
45498
|
+
nameMin: 'Minimum 2 characters',
|
|
45499
|
+
typePersonal: 'Personal',
|
|
45500
|
+
typePrivate: 'Private',
|
|
45501
|
+
typePublic: 'Public',
|
|
45502
|
+
typeBusiness: 'Business',
|
|
45503
|
+
successMsg: 'Organization created. Switching...',
|
|
45504
|
+
fillRequired: 'Please fill in all required fields.',
|
|
45308
45505
|
},
|
|
45309
45506
|
};
|
|
45507
|
+
|
|
45508
|
+
const DEFAULT_NAMESPACE$4 = 'CreateOrgModal';
|
|
45310
45509
|
/**
|
|
45311
|
-
*
|
|
45312
|
-
*
|
|
45510
|
+
* `val-create-org-modal` — modal de creación de organización (organism
|
|
45511
|
+
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
45512
|
+
* la vista Cuenta (y futuras vistas org-aware).
|
|
45513
|
+
*
|
|
45514
|
+
* Crea la org vía `OrgService.createOrg` y, en éxito, cambia a ella con
|
|
45515
|
+
* `OrgSwitchService.switchTo`. El formulario (nombre + tipo + descripción) se
|
|
45516
|
+
* construye una vez y se mantiene reactivo a idioma + estado de trabajo vía
|
|
45517
|
+
* effects `allowSignalWrites`.
|
|
45518
|
+
*
|
|
45519
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
45520
|
+
* `onSuccess(newOrg)`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar
|
|
45521
|
+
* texto en `slot=end`, título/subtítulo en el body con `val-display`/`val-title`.
|
|
45522
|
+
*
|
|
45523
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
45524
|
+
* `CreateOrgModal`.
|
|
45313
45525
|
*/
|
|
45314
|
-
|
|
45315
|
-
|
|
45316
|
-
|
|
45317
|
-
|
|
45318
|
-
|
|
45319
|
-
|
|
45320
|
-
|
|
45526
|
+
class CreateOrgModalComponent {
|
|
45527
|
+
constructor() {
|
|
45528
|
+
this.i18n = inject(I18nService);
|
|
45529
|
+
this.orgService = inject(OrgService);
|
|
45530
|
+
this.orgSwitch = inject(OrgSwitchService);
|
|
45531
|
+
this.toast = inject(ToastService);
|
|
45532
|
+
this.errors = inject(ValtechErrorService);
|
|
45533
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45534
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$4;
|
|
45535
|
+
this._busy = signal(false);
|
|
45536
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$4)) {
|
|
45537
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$4, CREATE_ORG_MODAL_I18N);
|
|
45538
|
+
}
|
|
45539
|
+
this.formMeta = signal(this.buildFormMeta());
|
|
45540
|
+
effect(() => {
|
|
45541
|
+
this.i18n.lang();
|
|
45542
|
+
this.formMeta.set(this.buildFormMeta());
|
|
45543
|
+
}, { allowSignalWrites: true });
|
|
45544
|
+
effect(() => {
|
|
45545
|
+
const working = this._busy();
|
|
45546
|
+
this.formMeta.update(meta => ({
|
|
45547
|
+
...meta,
|
|
45548
|
+
state: working ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
45549
|
+
actions: {
|
|
45550
|
+
...meta.actions,
|
|
45551
|
+
state: working ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
45552
|
+
},
|
|
45553
|
+
}));
|
|
45554
|
+
}, { allowSignalWrites: true });
|
|
45555
|
+
}
|
|
45556
|
+
async onSubmit(event) {
|
|
45557
|
+
if (this._busy())
|
|
45558
|
+
return;
|
|
45559
|
+
const name = event.fields['name'];
|
|
45560
|
+
const type = event.fields['type'];
|
|
45561
|
+
if (!name?.trim() || !type) {
|
|
45562
|
+
this.toast.show({
|
|
45563
|
+
message: this.t('fillRequired'),
|
|
45564
|
+
duration: 3000,
|
|
45565
|
+
color: 'dark',
|
|
45566
|
+
position: 'top',
|
|
45567
|
+
});
|
|
45568
|
+
return;
|
|
45569
|
+
}
|
|
45570
|
+
this._busy.set(true);
|
|
45571
|
+
try {
|
|
45572
|
+
const description = event.fields['description'];
|
|
45573
|
+
const newOrg = await firstValueFrom(this.orgService.createOrg({ name, type, description }));
|
|
45574
|
+
this.toast.show({
|
|
45575
|
+
message: this.t('successMsg'),
|
|
45576
|
+
color: 'dark',
|
|
45577
|
+
duration: 3500,
|
|
45578
|
+
});
|
|
45579
|
+
await this.orgSwitch.switchTo(newOrg.id);
|
|
45580
|
+
this.onSuccess?.(newOrg);
|
|
45581
|
+
this._modalRef?.dismiss(newOrg, 'confirm');
|
|
45582
|
+
}
|
|
45583
|
+
catch (err) {
|
|
45584
|
+
this.errors.handle(err, { i18nNamespace: this.i18nNamespace });
|
|
45585
|
+
}
|
|
45586
|
+
finally {
|
|
45587
|
+
this._busy.set(false);
|
|
45588
|
+
}
|
|
45589
|
+
}
|
|
45590
|
+
dismiss() {
|
|
45591
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
45592
|
+
}
|
|
45593
|
+
buildFormMeta() {
|
|
45594
|
+
const nameField = {
|
|
45595
|
+
token: 'new-org-name',
|
|
45596
|
+
name: 'name',
|
|
45597
|
+
label: this.t('nameLabel'),
|
|
45598
|
+
hint: '',
|
|
45599
|
+
placeholder: this.t('namePlaceholder'),
|
|
45600
|
+
type: InputType.TEXT,
|
|
45601
|
+
order: 1,
|
|
45602
|
+
validators: [Validators.required, Validators.minLength(2), Validators.maxLength(100)],
|
|
45603
|
+
errors: {
|
|
45604
|
+
required: this.t('nameRequired'),
|
|
45605
|
+
minlength: this.t('nameMin'),
|
|
45606
|
+
},
|
|
45607
|
+
value: '',
|
|
45608
|
+
state: ComponentStates.ENABLED,
|
|
45609
|
+
};
|
|
45610
|
+
const typeField = {
|
|
45611
|
+
token: 'new-org-type',
|
|
45612
|
+
name: 'type',
|
|
45613
|
+
label: this.t('typeLabel'),
|
|
45614
|
+
hint: '',
|
|
45615
|
+
placeholder: '',
|
|
45616
|
+
type: InputType.SELECT,
|
|
45617
|
+
order: 2,
|
|
45618
|
+
validators: [Validators.required],
|
|
45619
|
+
errors: {},
|
|
45620
|
+
value: 'PERSONAL',
|
|
45621
|
+
withDefault: 'PERSONAL',
|
|
45622
|
+
state: ComponentStates.ENABLED,
|
|
45623
|
+
options: [
|
|
45624
|
+
{ id: 'PERSONAL', name: this.t('typePersonal'), order: 1 },
|
|
45625
|
+
{ id: 'PRIVATE', name: this.t('typePrivate'), order: 2 },
|
|
45626
|
+
{ id: 'PUBLIC', name: this.t('typePublic'), order: 3 },
|
|
45627
|
+
{ id: 'BUSINESS', name: this.t('typeBusiness'), order: 4 },
|
|
45628
|
+
],
|
|
45629
|
+
};
|
|
45630
|
+
const descriptionField = {
|
|
45631
|
+
token: 'new-org-description',
|
|
45632
|
+
name: 'description',
|
|
45633
|
+
label: this.t('descriptionLabel'),
|
|
45634
|
+
hint: '',
|
|
45635
|
+
placeholder: this.t('descriptionPlaceholder'),
|
|
45636
|
+
type: InputType.TEXTAREA,
|
|
45637
|
+
order: 3,
|
|
45638
|
+
validators: [],
|
|
45639
|
+
errors: {},
|
|
45640
|
+
value: '',
|
|
45641
|
+
state: ComponentStates.ENABLED,
|
|
45642
|
+
};
|
|
45643
|
+
const submitButton = {
|
|
45644
|
+
text: this.t('createCta'),
|
|
45645
|
+
color: 'dark',
|
|
45646
|
+
type: 'submit',
|
|
45647
|
+
fill: 'solid',
|
|
45648
|
+
size: 'default',
|
|
45649
|
+
shape: 'round',
|
|
45650
|
+
expand: 'block',
|
|
45651
|
+
state: ComponentStates.ENABLED,
|
|
45652
|
+
token: 'new-org-submit',
|
|
45653
|
+
};
|
|
45654
|
+
return {
|
|
45655
|
+
name: '',
|
|
45656
|
+
state: ComponentStates.ENABLED,
|
|
45657
|
+
sections: [
|
|
45658
|
+
{
|
|
45659
|
+
name: '',
|
|
45660
|
+
order: 1,
|
|
45661
|
+
fields: [nameField, typeField, descriptionField],
|
|
45662
|
+
},
|
|
45663
|
+
],
|
|
45664
|
+
actions: submitButton,
|
|
45665
|
+
};
|
|
45666
|
+
}
|
|
45667
|
+
t(key) {
|
|
45668
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
45669
|
+
}
|
|
45670
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CreateOrgModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
45671
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CreateOrgModalComponent, isStandalone: true, selector: "val-create-org-modal", inputs: { _modalRef: "_modalRef", onSuccess: "onSuccess", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
45672
|
+
<ion-header>
|
|
45673
|
+
<ion-toolbar>
|
|
45674
|
+
<ion-buttons slot="end">
|
|
45675
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
45676
|
+
<strong>{{ t('close') }}</strong>
|
|
45677
|
+
</ion-button>
|
|
45678
|
+
</ion-buttons>
|
|
45679
|
+
</ion-toolbar>
|
|
45680
|
+
</ion-header>
|
|
45681
|
+
<ion-content class="ion-padding">
|
|
45682
|
+
<val-display [props]="{ content: t('pageTitle'), size: 'small', color: 'dark' }" />
|
|
45683
|
+
<val-title
|
|
45684
|
+
[props]="{
|
|
45685
|
+
content: t('pageDescription'),
|
|
45686
|
+
size: 'large',
|
|
45687
|
+
color: '',
|
|
45688
|
+
bold: false,
|
|
45689
|
+
}"
|
|
45690
|
+
/>
|
|
45691
|
+
<val-form [props]="formMeta()" (onSubmit)="onSubmit($event)" />
|
|
45692
|
+
</ion-content>
|
|
45693
|
+
`, 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"] }] }); }
|
|
45694
|
+
}
|
|
45695
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CreateOrgModalComponent, decorators: [{
|
|
45696
|
+
type: Component,
|
|
45697
|
+
args: [{
|
|
45698
|
+
selector: 'val-create-org-modal',
|
|
45699
|
+
standalone: true,
|
|
45700
|
+
imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, FormComponent, DisplayComponent, TitleComponent],
|
|
45701
|
+
template: `
|
|
45702
|
+
<ion-header>
|
|
45703
|
+
<ion-toolbar>
|
|
45704
|
+
<ion-buttons slot="end">
|
|
45705
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
45706
|
+
<strong>{{ t('close') }}</strong>
|
|
45707
|
+
</ion-button>
|
|
45708
|
+
</ion-buttons>
|
|
45709
|
+
</ion-toolbar>
|
|
45710
|
+
</ion-header>
|
|
45711
|
+
<ion-content class="ion-padding">
|
|
45712
|
+
<val-display [props]="{ content: t('pageTitle'), size: 'small', color: 'dark' }" />
|
|
45713
|
+
<val-title
|
|
45714
|
+
[props]="{
|
|
45715
|
+
content: t('pageDescription'),
|
|
45716
|
+
size: 'large',
|
|
45717
|
+
color: '',
|
|
45718
|
+
bold: false,
|
|
45719
|
+
}"
|
|
45720
|
+
/>
|
|
45721
|
+
<val-form [props]="formMeta()" (onSubmit)="onSubmit($event)" />
|
|
45722
|
+
</ion-content>
|
|
45723
|
+
`,
|
|
45724
|
+
}]
|
|
45725
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
45726
|
+
type: Input
|
|
45727
|
+
}], onSuccess: [{
|
|
45728
|
+
type: Input
|
|
45729
|
+
}], i18nNamespace: [{
|
|
45730
|
+
type: Input
|
|
45731
|
+
}] } });
|
|
45732
|
+
|
|
45733
|
+
/**
|
|
45734
|
+
* Defaults i18n (es/en) embebidos en `val-delete-account-modal`. Auto-registrados
|
|
45735
|
+
* en el constructor del componente si el consumer no proveyó el namespace
|
|
45736
|
+
* (`Settings.DeleteAccount` por default). SOLO incluye las keys que el modal usa.
|
|
45737
|
+
*/
|
|
45738
|
+
const DELETE_ACCOUNT_MODAL_I18N = {
|
|
45739
|
+
es: {
|
|
45740
|
+
title: 'Eliminar cuenta',
|
|
45741
|
+
warningPassword: 'Esta acción es permanente y no se puede deshacer. Se eliminarán tu cuenta, sesiones activas, organizaciones personales y todos los datos asociados.',
|
|
45742
|
+
passwordLabel: 'Contraseña actual',
|
|
45743
|
+
passwordPlaceholder: 'Ingresa tu contraseña',
|
|
45744
|
+
passwordRequired: 'La contraseña es requerida',
|
|
45745
|
+
warningSendCode: 'Tu cuenta está vinculada a un proveedor externo. Para confirmar la eliminación, enviaremos un código de verificación a tu correo electrónico.',
|
|
45746
|
+
sendCodeCta: 'Enviar código de confirmación',
|
|
45747
|
+
warningEnterCode: 'Ingresa el código que enviamos a tu correo. Expira en 15 minutos.',
|
|
45748
|
+
codeLabel: 'Código de verificación',
|
|
45749
|
+
codePlaceholder: 'Código de 6 dígitos',
|
|
45750
|
+
codeRequired: 'El código es requerido',
|
|
45751
|
+
confirmCta: 'Eliminar mi cuenta',
|
|
45752
|
+
close: 'Cancelar',
|
|
45753
|
+
resend: 'Reenviar código',
|
|
45754
|
+
},
|
|
45755
|
+
en: {
|
|
45756
|
+
title: 'Delete account',
|
|
45757
|
+
warningPassword: 'This action is permanent and cannot be undone. Your account, active sessions, personal organizations and all associated data will be permanently deleted.',
|
|
45758
|
+
passwordLabel: 'Current password',
|
|
45759
|
+
passwordPlaceholder: 'Enter your password',
|
|
45760
|
+
passwordRequired: 'Password is required',
|
|
45761
|
+
warningSendCode: "Your account is linked to an external provider. To confirm deletion, we'll send a verification code to your email address.",
|
|
45762
|
+
sendCodeCta: 'Send confirmation code',
|
|
45763
|
+
warningEnterCode: 'Enter the code we sent to your email. It expires in 15 minutes.',
|
|
45764
|
+
codeLabel: 'Verification code',
|
|
45765
|
+
codePlaceholder: '6-digit code',
|
|
45766
|
+
codeRequired: 'Code is required',
|
|
45767
|
+
confirmCta: 'Delete my account',
|
|
45768
|
+
close: 'Cancel',
|
|
45769
|
+
resend: 'Resend code',
|
|
45770
|
+
},
|
|
45321
45771
|
};
|
|
45322
|
-
|
|
45323
|
-
const
|
|
45324
|
-
const FENCE_RE = /^```([\w-]*)\s*$/;
|
|
45325
|
-
const HEADING_RE = /^(#{1,6})\s+(.+)$/;
|
|
45326
|
-
const SEPARATOR_RE = /^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/;
|
|
45327
|
-
const UNORDERED_RE = /^\s*[-*+]\s+(.+)$/;
|
|
45328
|
-
const CHECKLIST_RE = /^\s*[-*+]\s+\[([ xX])\]\s+(.+)$/;
|
|
45329
|
-
const ORDERED_RE = /^\s*\d+\.\s+(.+)$/;
|
|
45330
|
-
const TABLE_DIVIDER_RE = /^\s*\|?[\s:|-]+\|?\s*$/;
|
|
45331
|
-
const TABLE_ROW_RE = /^\s*\|(.+)\|\s*$/;
|
|
45772
|
+
|
|
45773
|
+
const DEFAULT_NAMESPACE$3 = 'Settings.DeleteAccount';
|
|
45332
45774
|
/**
|
|
45333
|
-
*
|
|
45334
|
-
*
|
|
45775
|
+
* `val-delete-account-modal` — modal de eliminación de cuenta (organism,
|
|
45776
|
+
* cuenta-específico). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
45335
45777
|
*
|
|
45336
|
-
*
|
|
45337
|
-
*
|
|
45338
|
-
*
|
|
45339
|
-
*
|
|
45340
|
-
*
|
|
45341
|
-
*
|
|
45342
|
-
*
|
|
45343
|
-
*
|
|
45344
|
-
*
|
|
45778
|
+
* Decide el flujo según si la cuenta tiene contraseña:
|
|
45779
|
+
* - **con password** → pide la contraseña actual y la verifica vía
|
|
45780
|
+
* `auth.deleteAccount({ password })`.
|
|
45781
|
+
* - **sin password** (cuenta OAuth) → envía un código por email
|
|
45782
|
+
* (`auth.sendDeleteAccountCode()`) y lo pide para confirmar
|
|
45783
|
+
* (`auth.deleteAccount({ code })`).
|
|
45784
|
+
*
|
|
45785
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` para
|
|
45786
|
+
* cerrar desde dentro. Header canónico (Regla #5): sin `ion-title`, botón Cerrar
|
|
45787
|
+
* texto en `slot=end`, título/subtítulo en el body vía `val-form`.
|
|
45788
|
+
*
|
|
45789
|
+
* Auto-registra sus defaults i18n (es/en) en el constructor si el consumer no
|
|
45790
|
+
* proveyó el namespace `Settings.DeleteAccount`.
|
|
45345
45791
|
*/
|
|
45346
|
-
|
|
45347
|
-
|
|
45348
|
-
|
|
45349
|
-
|
|
45350
|
-
|
|
45351
|
-
|
|
45352
|
-
|
|
45353
|
-
|
|
45354
|
-
|
|
45355
|
-
|
|
45356
|
-
|
|
45792
|
+
class DeleteAccountModalComponent {
|
|
45793
|
+
constructor() {
|
|
45794
|
+
this.auth = inject(AuthService);
|
|
45795
|
+
this.errors = inject(ValtechErrorService);
|
|
45796
|
+
this.i18n = inject(I18nService);
|
|
45797
|
+
this.toast = inject(ToastService);
|
|
45798
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45799
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$3;
|
|
45800
|
+
this.hasPassword = signal(null);
|
|
45801
|
+
this.codeSent = signal(false);
|
|
45802
|
+
this.formState = signal(ComponentStates.ENABLED);
|
|
45803
|
+
this.t = (key) => this.i18n.t(key, this.i18nNamespace);
|
|
45804
|
+
this.passwordFormProps = computed(() => ({
|
|
45805
|
+
name: this.t('title'),
|
|
45806
|
+
state: this.formState(),
|
|
45807
|
+
sections: [
|
|
45808
|
+
{
|
|
45809
|
+
name: this.t('warningPassword'),
|
|
45810
|
+
order: 0,
|
|
45811
|
+
fields: [
|
|
45812
|
+
{
|
|
45813
|
+
token: 'delete-password',
|
|
45814
|
+
name: 'password',
|
|
45815
|
+
label: this.t('passwordLabel'),
|
|
45816
|
+
hint: '',
|
|
45817
|
+
placeholder: this.t('passwordPlaceholder'),
|
|
45818
|
+
type: InputType.PASSWORD,
|
|
45819
|
+
order: 0,
|
|
45820
|
+
validators: [Validators.required],
|
|
45821
|
+
errors: { required: this.t('passwordRequired') },
|
|
45822
|
+
state: ComponentStates.ENABLED,
|
|
45823
|
+
},
|
|
45824
|
+
],
|
|
45825
|
+
},
|
|
45826
|
+
],
|
|
45827
|
+
actions: this.submitBtn('delete-password-submit', 'confirmCta'),
|
|
45828
|
+
}));
|
|
45829
|
+
this.sendCodeFormProps = computed(() => ({
|
|
45830
|
+
name: this.t('title'),
|
|
45831
|
+
state: this.formState(),
|
|
45832
|
+
sections: [
|
|
45833
|
+
{
|
|
45834
|
+
name: this.t('warningSendCode'),
|
|
45835
|
+
order: 0,
|
|
45836
|
+
fields: [],
|
|
45837
|
+
},
|
|
45838
|
+
],
|
|
45839
|
+
actions: this.submitBtn('delete-send-code-submit', 'sendCodeCta'),
|
|
45840
|
+
}));
|
|
45841
|
+
this.codeFormProps = computed(() => ({
|
|
45842
|
+
name: this.t('title'),
|
|
45843
|
+
state: this.formState(),
|
|
45844
|
+
sections: [
|
|
45845
|
+
{
|
|
45846
|
+
name: this.t('warningEnterCode'),
|
|
45847
|
+
order: 0,
|
|
45848
|
+
fields: [
|
|
45849
|
+
{
|
|
45850
|
+
token: 'delete-code',
|
|
45851
|
+
name: 'code',
|
|
45852
|
+
label: this.t('codeLabel'),
|
|
45853
|
+
hint: '',
|
|
45854
|
+
placeholder: this.t('codePlaceholder'),
|
|
45855
|
+
type: InputType.TEXT,
|
|
45856
|
+
order: 0,
|
|
45857
|
+
validators: [Validators.required],
|
|
45858
|
+
errors: { required: this.t('codeRequired') },
|
|
45859
|
+
state: ComponentStates.ENABLED,
|
|
45860
|
+
},
|
|
45861
|
+
],
|
|
45862
|
+
},
|
|
45863
|
+
],
|
|
45864
|
+
actions: this.submitBtn('delete-code-submit', 'confirmCta'),
|
|
45865
|
+
}));
|
|
45866
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$3)) {
|
|
45867
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$3, DELETE_ACCOUNT_MODAL_I18N);
|
|
45357
45868
|
}
|
|
45358
|
-
|
|
45359
|
-
|
|
45360
|
-
|
|
45361
|
-
|
|
45362
|
-
|
|
45363
|
-
|
|
45364
|
-
|
|
45365
|
-
|
|
45366
|
-
|
|
45367
|
-
|
|
45368
|
-
|
|
45369
|
-
|
|
45370
|
-
|
|
45869
|
+
}
|
|
45870
|
+
ngOnInit() {
|
|
45871
|
+
firstValueFrom(this.auth.getProfile())
|
|
45872
|
+
.then(profile => this.hasPassword.set(profile.hasPassword ?? true))
|
|
45873
|
+
.catch(() => this.hasPassword.set(true));
|
|
45874
|
+
}
|
|
45875
|
+
submitBtn(token, textKey) {
|
|
45876
|
+
return {
|
|
45877
|
+
text: this.t(textKey),
|
|
45878
|
+
type: 'submit',
|
|
45879
|
+
expand: 'block',
|
|
45880
|
+
fill: 'solid',
|
|
45881
|
+
color: 'dark',
|
|
45882
|
+
size: 'default',
|
|
45883
|
+
token,
|
|
45884
|
+
state: ComponentStates.ENABLED,
|
|
45885
|
+
};
|
|
45886
|
+
}
|
|
45887
|
+
close() {
|
|
45888
|
+
this._modalRef?.dismiss(undefined, 'cancel');
|
|
45889
|
+
}
|
|
45890
|
+
async onPasswordSubmit(event) {
|
|
45891
|
+
const password = event.fields['password'];
|
|
45892
|
+
if (!password) {
|
|
45893
|
+
this.toast.show({
|
|
45894
|
+
message: this.t('passwordRequired'),
|
|
45895
|
+
duration: 3000,
|
|
45896
|
+
color: 'dark',
|
|
45897
|
+
position: 'top',
|
|
45371
45898
|
});
|
|
45372
|
-
|
|
45899
|
+
return;
|
|
45373
45900
|
}
|
|
45374
|
-
|
|
45375
|
-
|
|
45376
|
-
|
|
45377
|
-
body.push(lines[i]);
|
|
45378
|
-
i++;
|
|
45379
|
-
}
|
|
45380
|
-
while (body.length && body[body.length - 1].trim() === '')
|
|
45381
|
-
body.pop();
|
|
45382
|
-
elements.push({
|
|
45383
|
-
type: 'code',
|
|
45384
|
-
props: { code: body.join('\n'), language: 'text', theme: 'dark' },
|
|
45385
|
-
});
|
|
45386
|
-
continue;
|
|
45901
|
+
this.formState.set(ComponentStates.WORKING);
|
|
45902
|
+
try {
|
|
45903
|
+
await firstValueFrom(this.auth.deleteAccount({ password }));
|
|
45387
45904
|
}
|
|
45388
|
-
|
|
45389
|
-
|
|
45390
|
-
|
|
45391
|
-
continue;
|
|
45905
|
+
catch (err) {
|
|
45906
|
+
this.errors.handle(err, { context: 'delete-account.password' });
|
|
45907
|
+
this.formState.set(ComponentStates.ENABLED);
|
|
45392
45908
|
}
|
|
45393
|
-
|
|
45394
|
-
|
|
45395
|
-
|
|
45396
|
-
|
|
45397
|
-
|
|
45909
|
+
}
|
|
45910
|
+
async onSendCode() {
|
|
45911
|
+
this.formState.set(ComponentStates.WORKING);
|
|
45912
|
+
try {
|
|
45913
|
+
await firstValueFrom(this.auth.sendDeleteAccountCode());
|
|
45914
|
+
this.codeSent.set(true);
|
|
45398
45915
|
}
|
|
45399
|
-
|
|
45400
|
-
|
|
45401
|
-
while (i < lines.length && lines[i].startsWith('>')) {
|
|
45402
|
-
block.push(lines[i]);
|
|
45403
|
-
i++;
|
|
45404
|
-
}
|
|
45405
|
-
elements.push(makeQuoteOrCallout(block, labels));
|
|
45406
|
-
continue;
|
|
45916
|
+
catch (err) {
|
|
45917
|
+
this.errors.handle(err, { context: 'delete-account.send-code' });
|
|
45407
45918
|
}
|
|
45408
|
-
|
|
45409
|
-
|
|
45410
|
-
while (i < lines.length && TABLE_ROW_RE.test(lines[i])) {
|
|
45411
|
-
rows.push(lines[i]);
|
|
45412
|
-
i++;
|
|
45413
|
-
}
|
|
45414
|
-
elements.push(...makeTable(rows));
|
|
45415
|
-
continue;
|
|
45919
|
+
finally {
|
|
45920
|
+
this.formState.set(ComponentStates.ENABLED);
|
|
45416
45921
|
}
|
|
45417
|
-
|
|
45418
|
-
|
|
45419
|
-
|
|
45420
|
-
|
|
45421
|
-
|
|
45422
|
-
|
|
45423
|
-
|
|
45424
|
-
|
|
45425
|
-
|
|
45426
|
-
|
|
45427
|
-
|
|
45428
|
-
|
|
45429
|
-
|
|
45430
|
-
|
|
45431
|
-
|
|
45432
|
-
items.push({ text: processInlineBold(ord[1].trim()) });
|
|
45433
|
-
else if (unord && listType !== 'ordered')
|
|
45434
|
-
items.push({ text: processInlineBold(unord[1].trim()) });
|
|
45435
|
-
else
|
|
45436
|
-
break;
|
|
45437
|
-
i++;
|
|
45438
|
-
}
|
|
45439
|
-
elements.push({ type: 'list', props: { items, listType } });
|
|
45440
|
-
continue;
|
|
45922
|
+
}
|
|
45923
|
+
async onResendCode() {
|
|
45924
|
+
this.codeSent.set(false);
|
|
45925
|
+
await this.onSendCode();
|
|
45926
|
+
}
|
|
45927
|
+
async onCodeSubmit(event) {
|
|
45928
|
+
const code = event.fields['code'];
|
|
45929
|
+
if (!code) {
|
|
45930
|
+
this.toast.show({
|
|
45931
|
+
message: this.t('codeRequired'),
|
|
45932
|
+
duration: 3000,
|
|
45933
|
+
color: 'dark',
|
|
45934
|
+
position: 'top',
|
|
45935
|
+
});
|
|
45936
|
+
return;
|
|
45441
45937
|
}
|
|
45442
|
-
|
|
45443
|
-
|
|
45444
|
-
|
|
45445
|
-
i++;
|
|
45938
|
+
this.formState.set(ComponentStates.WORKING);
|
|
45939
|
+
try {
|
|
45940
|
+
await firstValueFrom(this.auth.deleteAccount({ code }));
|
|
45446
45941
|
}
|
|
45447
|
-
|
|
45448
|
-
|
|
45449
|
-
|
|
45450
|
-
type: 'paragraph',
|
|
45451
|
-
props: {
|
|
45452
|
-
content: text,
|
|
45453
|
-
size: 'medium',
|
|
45454
|
-
color: 'dark',
|
|
45455
|
-
bold: false,
|
|
45456
|
-
processLinks: true,
|
|
45457
|
-
allowPartialBold: true,
|
|
45458
|
-
},
|
|
45459
|
-
});
|
|
45942
|
+
catch (err) {
|
|
45943
|
+
this.errors.handle(err, { context: 'delete-account.code' });
|
|
45944
|
+
this.formState.set(ComponentStates.ENABLED);
|
|
45460
45945
|
}
|
|
45461
45946
|
}
|
|
45462
|
-
|
|
45463
|
-
|
|
45947
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DeleteAccountModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
45948
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: DeleteAccountModalComponent, isStandalone: true, selector: "val-delete-account-modal", inputs: { _modalRef: "_modalRef", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
45949
|
+
<ion-header>
|
|
45950
|
+
<ion-toolbar>
|
|
45951
|
+
<ion-buttons slot="end">
|
|
45952
|
+
<ion-button fill="clear" color="dark" (click)="close()">
|
|
45953
|
+
<strong>{{ t('close') }}</strong>
|
|
45954
|
+
</ion-button>
|
|
45955
|
+
</ion-buttons>
|
|
45956
|
+
</ion-toolbar>
|
|
45957
|
+
</ion-header>
|
|
45958
|
+
|
|
45959
|
+
<ion-content class="ion-padding">
|
|
45960
|
+
<section class="modal-form-section">
|
|
45961
|
+
@if (hasPassword() === null) {
|
|
45962
|
+
<div class="spinner-center">
|
|
45963
|
+
<ion-spinner name="crescent" />
|
|
45964
|
+
</div>
|
|
45965
|
+
} @else if (hasPassword()) {
|
|
45966
|
+
<val-form [props]="passwordFormProps()" (onSubmit)="onPasswordSubmit($event)" />
|
|
45967
|
+
} @else if (!codeSent()) {
|
|
45968
|
+
<val-form [props]="sendCodeFormProps()" (onSubmit)="onSendCode()" />
|
|
45969
|
+
} @else {
|
|
45970
|
+
<val-form [props]="codeFormProps()" (onSubmit)="onCodeSubmit($event)" />
|
|
45971
|
+
<div class="resend-row">
|
|
45972
|
+
<ion-button
|
|
45973
|
+
fill="clear"
|
|
45974
|
+
color="medium"
|
|
45975
|
+
size="small"
|
|
45976
|
+
[disabled]="formState() === 'WORKING'"
|
|
45977
|
+
(click)="onResendCode()"
|
|
45978
|
+
>
|
|
45979
|
+
{{ t('resend') }}
|
|
45980
|
+
</ion-button>
|
|
45981
|
+
</div>
|
|
45982
|
+
}
|
|
45983
|
+
</section>
|
|
45984
|
+
</ion-content>
|
|
45985
|
+
`, isInline: true, styles: [".modal-form-section{display:flex;flex-direction:column;gap:16px;max-width:420px;margin:0 auto;padding-top:8px}.resend-row{display:flex;justify-content:center;margin-top:-8px}.spinner-center{display:flex;justify-content:center;padding-top:32px}\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: FormComponent, selector: "val-form", inputs: ["props"], outputs: ["onSubmit", "onInvalid", "onSelectChange"] }] }); }
|
|
45986
|
+
}
|
|
45987
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DeleteAccountModalComponent, decorators: [{
|
|
45988
|
+
type: Component,
|
|
45989
|
+
args: [{ selector: 'val-delete-account-modal', standalone: true, imports: [IonHeader, IonToolbar, IonButtons, IonButton, IonContent, IonSpinner, FormComponent], template: `
|
|
45990
|
+
<ion-header>
|
|
45991
|
+
<ion-toolbar>
|
|
45992
|
+
<ion-buttons slot="end">
|
|
45993
|
+
<ion-button fill="clear" color="dark" (click)="close()">
|
|
45994
|
+
<strong>{{ t('close') }}</strong>
|
|
45995
|
+
</ion-button>
|
|
45996
|
+
</ion-buttons>
|
|
45997
|
+
</ion-toolbar>
|
|
45998
|
+
</ion-header>
|
|
45999
|
+
|
|
46000
|
+
<ion-content class="ion-padding">
|
|
46001
|
+
<section class="modal-form-section">
|
|
46002
|
+
@if (hasPassword() === null) {
|
|
46003
|
+
<div class="spinner-center">
|
|
46004
|
+
<ion-spinner name="crescent" />
|
|
46005
|
+
</div>
|
|
46006
|
+
} @else if (hasPassword()) {
|
|
46007
|
+
<val-form [props]="passwordFormProps()" (onSubmit)="onPasswordSubmit($event)" />
|
|
46008
|
+
} @else if (!codeSent()) {
|
|
46009
|
+
<val-form [props]="sendCodeFormProps()" (onSubmit)="onSendCode()" />
|
|
46010
|
+
} @else {
|
|
46011
|
+
<val-form [props]="codeFormProps()" (onSubmit)="onCodeSubmit($event)" />
|
|
46012
|
+
<div class="resend-row">
|
|
46013
|
+
<ion-button
|
|
46014
|
+
fill="clear"
|
|
46015
|
+
color="medium"
|
|
46016
|
+
size="small"
|
|
46017
|
+
[disabled]="formState() === 'WORKING'"
|
|
46018
|
+
(click)="onResendCode()"
|
|
46019
|
+
>
|
|
46020
|
+
{{ t('resend') }}
|
|
46021
|
+
</ion-button>
|
|
46022
|
+
</div>
|
|
46023
|
+
}
|
|
46024
|
+
</section>
|
|
46025
|
+
</ion-content>
|
|
46026
|
+
`, styles: [".modal-form-section{display:flex;flex-direction:column;gap:16px;max-width:420px;margin:0 auto;padding-top:8px}.resend-row{display:flex;justify-content:center;margin-top:-8px}.spinner-center{display:flex;justify-content:center;padding-top:32px}\n"] }]
|
|
46027
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
46028
|
+
type: Input
|
|
46029
|
+
}], i18nNamespace: [{
|
|
46030
|
+
type: Input
|
|
46031
|
+
}] } });
|
|
46032
|
+
|
|
46033
|
+
/**
|
|
46034
|
+
* Defaults i18n (es/en) embebidos en `val-org-info-sheet`. Auto-registrados en el
|
|
46035
|
+
* constructor del componente si el consumer no proveyó el namespace
|
|
46036
|
+
* (`OrgInfoSheet`). Cubre los textos de los 3 features (que en la versión inline
|
|
46037
|
+
* de showcase estaban hardcoded) más fallbacks de título/subtítulo/closeLabel.
|
|
46038
|
+
*
|
|
46039
|
+
* `title`/`subtitle`/`body`/`closeLabel` los suele pasar el consumer ya resueltos
|
|
46040
|
+
* por props (patrón del resto de modales); las keys `feature*` se auto-resuelven
|
|
46041
|
+
* desde este namespace.
|
|
46042
|
+
*/
|
|
46043
|
+
const ORG_INFO_SHEET_I18N = {
|
|
46044
|
+
es: {
|
|
46045
|
+
title: '¿Qué son las organizaciones?',
|
|
46046
|
+
subtitle: 'Todo lo que necesitas saber',
|
|
46047
|
+
close: 'Cerrar',
|
|
46048
|
+
featureCollabTitle: 'Colaboración',
|
|
46049
|
+
featureCollabDesc: 'Separa proyectos y datos por empresa o equipo.',
|
|
46050
|
+
featureSwitchTitle: 'Cambio rápido',
|
|
46051
|
+
featureSwitchDesc: 'Cambia entre organizaciones en cualquier momento.',
|
|
46052
|
+
featureInviteTitle: 'Invitaciones',
|
|
46053
|
+
featureInviteDesc: 'Invita a otros a unirse mediante email.',
|
|
46054
|
+
},
|
|
46055
|
+
en: {
|
|
46056
|
+
title: 'What are organizations?',
|
|
46057
|
+
subtitle: 'Everything you need to know',
|
|
46058
|
+
close: 'Close',
|
|
46059
|
+
featureCollabTitle: 'Collaboration',
|
|
46060
|
+
featureCollabDesc: 'Separate projects and data by company or team.',
|
|
46061
|
+
featureSwitchTitle: 'Quick switch',
|
|
46062
|
+
featureSwitchDesc: 'Switch between organizations at any time.',
|
|
46063
|
+
featureInviteTitle: 'Invitations',
|
|
46064
|
+
featureInviteDesc: 'Invite others to join via email.',
|
|
46065
|
+
},
|
|
46066
|
+
};
|
|
46067
|
+
|
|
46068
|
+
const DEFAULT_NAMESPACE$2 = 'OrgInfoSheet';
|
|
46069
|
+
/**
|
|
46070
|
+
* `val-org-info-sheet` — sheet informativo "¿Qué son las organizaciones?".
|
|
46071
|
+
* Extraído del `OrgInfoSheetComponent` inline de `AccountPage` bajo el proceso de
|
|
46072
|
+
* ADR-021.
|
|
46073
|
+
*
|
|
46074
|
+
* El consumer pasa `title`/`subtitle`/`body`/`closeLabel` ya resueltos por props
|
|
46075
|
+
* (patrón del resto de modales del factory). Los textos de los 3 features
|
|
46076
|
+
* (Colaboración / Cambio rápido / Invitaciones), que en la versión inline estaban
|
|
46077
|
+
* hardcoded, ahora se auto-resuelven desde el namespace `OrgInfoSheet`
|
|
46078
|
+
* (auto-registrado en el constructor).
|
|
46079
|
+
*
|
|
46080
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps`. Header
|
|
46081
|
+
* canónico (Regla #5): sin `ion-title`, botón Cerrar texto en `slot=end`,
|
|
46082
|
+
* título/subtítulo en el body con `val-display`/`val-title`.
|
|
46083
|
+
*/
|
|
46084
|
+
class OrgInfoSheetComponent {
|
|
46085
|
+
constructor() {
|
|
46086
|
+
this.i18n = inject(I18nService);
|
|
46087
|
+
/** Título principal (resuelto por el consumer). Fallback al namespace propio. */
|
|
46088
|
+
this.title = '';
|
|
46089
|
+
/** Subtítulo (resuelto por el consumer). Fallback al namespace propio. */
|
|
46090
|
+
this.subtitle = '';
|
|
46091
|
+
/** Cuerpo en párrafos separados por doble salto de línea (resuelto por el consumer). */
|
|
46092
|
+
this.body = '';
|
|
46093
|
+
/** Label del botón cerrar (resuelto por el consumer). Fallback al namespace propio. */
|
|
46094
|
+
this.closeLabel = '';
|
|
46095
|
+
/** Props del botón cerrar del footer (el consumer puede pasar custom). */
|
|
46096
|
+
this.closeProps = {
|
|
46097
|
+
text: 'Cerrar',
|
|
46098
|
+
fill: 'outline',
|
|
46099
|
+
color: 'dark',
|
|
46100
|
+
size: 'default',
|
|
46101
|
+
expand: 'block',
|
|
46102
|
+
type: 'button',
|
|
46103
|
+
};
|
|
46104
|
+
this.resolvedTitle = computed(() => this.title || this.tt('title'));
|
|
46105
|
+
this.resolvedSubtitle = computed(() => this.subtitle || this.tt('subtitle'));
|
|
46106
|
+
this.resolvedCloseLabel = computed(() => this.closeLabel || this.tt('close'));
|
|
46107
|
+
this.paragraphs = computed(() => this.body.split('\n\n').filter(Boolean));
|
|
46108
|
+
this.resolvedCloseProps = computed(() => ({
|
|
46109
|
+
...this.closeProps,
|
|
46110
|
+
text: this.closeProps.text || this.resolvedCloseLabel(),
|
|
46111
|
+
}));
|
|
46112
|
+
addIcons({ peopleOutline, swapHorizontalOutline, mailOutline });
|
|
46113
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$2)) {
|
|
46114
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$2, ORG_INFO_SHEET_I18N);
|
|
46115
|
+
}
|
|
46116
|
+
}
|
|
46117
|
+
dismiss() {
|
|
46118
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
46119
|
+
}
|
|
46120
|
+
tt(key) {
|
|
46121
|
+
return this.i18n.t(key, DEFAULT_NAMESPACE$2);
|
|
46122
|
+
}
|
|
46123
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46124
|
+
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: `
|
|
46125
|
+
<ion-header>
|
|
46126
|
+
<ion-toolbar>
|
|
46127
|
+
<ion-buttons slot="end">
|
|
46128
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
46129
|
+
<strong>{{ resolvedCloseLabel() }}</strong>
|
|
46130
|
+
</ion-button>
|
|
46131
|
+
</ion-buttons>
|
|
46132
|
+
</ion-toolbar>
|
|
46133
|
+
</ion-header>
|
|
46134
|
+
|
|
46135
|
+
<ion-content class="ion-padding">
|
|
46136
|
+
<val-display [props]="{ content: resolvedTitle(), size: 'small', color: 'dark' }" />
|
|
46137
|
+
<val-title [props]="{ content: resolvedSubtitle(), size: 'large', color: '', bold: false }" />
|
|
46138
|
+
|
|
46139
|
+
<div class="info-features">
|
|
46140
|
+
<div class="info-feature">
|
|
46141
|
+
<ion-icon name="people-outline" class="info-feature__icon" />
|
|
46142
|
+
<div>
|
|
46143
|
+
<div class="info-feature__title">{{ tt('featureCollabTitle') }}</div>
|
|
46144
|
+
<div class="info-feature__desc">{{ tt('featureCollabDesc') }}</div>
|
|
46145
|
+
</div>
|
|
46146
|
+
</div>
|
|
46147
|
+
<div class="info-feature">
|
|
46148
|
+
<ion-icon name="swap-horizontal-outline" class="info-feature__icon" />
|
|
46149
|
+
<div>
|
|
46150
|
+
<div class="info-feature__title">{{ tt('featureSwitchTitle') }}</div>
|
|
46151
|
+
<div class="info-feature__desc">{{ tt('featureSwitchDesc') }}</div>
|
|
46152
|
+
</div>
|
|
46153
|
+
</div>
|
|
46154
|
+
<div class="info-feature">
|
|
46155
|
+
<ion-icon name="mail-outline" class="info-feature__icon" />
|
|
46156
|
+
<div>
|
|
46157
|
+
<div class="info-feature__title">{{ tt('featureInviteTitle') }}</div>
|
|
46158
|
+
<div class="info-feature__desc">{{ tt('featureInviteDesc') }}</div>
|
|
46159
|
+
</div>
|
|
46160
|
+
</div>
|
|
46161
|
+
</div>
|
|
46162
|
+
|
|
46163
|
+
@for (para of paragraphs(); track $index) {
|
|
46164
|
+
<val-text
|
|
46165
|
+
[props]="{
|
|
46166
|
+
size: 'medium',
|
|
46167
|
+
color: 'dark',
|
|
46168
|
+
bold: false,
|
|
46169
|
+
content: para,
|
|
46170
|
+
}"
|
|
46171
|
+
/>
|
|
46172
|
+
}
|
|
46173
|
+
|
|
46174
|
+
<div class="sheet-footer">
|
|
46175
|
+
<val-button [props]="resolvedCloseProps()" (click)="dismiss()" />
|
|
46176
|
+
</div>
|
|
46177
|
+
</ion-content>
|
|
46178
|
+
`, isInline: true, styles: ["ion-content{--padding-bottom: 32px}val-display{margin-bottom:4px;display:block}val-title{margin-bottom:8px;display:block}.info-features{display:flex;flex-direction:column;gap:12px;margin:16px 0}.info-feature{display:flex;align-items:flex-start;gap:14px;padding:12px 14px;border-radius:10px;background:var(--ion-color-light, #f4f5f8)}:host-context(body.dark) .info-feature,:host-context(html.ion-palette-dark) .info-feature,:host-context([data-theme=\"dark\"]) .info-feature{background:#ffffff0d}.info-feature__icon{font-size:22px;color:var(--ion-color-primary);flex-shrink:0;margin-top:2px}.info-feature__title{font-weight:600;font-size:.9rem;color:var(--ion-color-dark)}.info-feature__desc{font-size:.82rem;color:var(--ion-color-medium);margin-top:2px}.sheet-footer{margin-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: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { 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"] }] }); }
|
|
46179
|
+
}
|
|
46180
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, decorators: [{
|
|
46181
|
+
type: Component,
|
|
46182
|
+
args: [{ selector: 'val-org-info-sheet', standalone: true, imports: [
|
|
46183
|
+
IonHeader,
|
|
46184
|
+
IonToolbar,
|
|
46185
|
+
IonButtons,
|
|
46186
|
+
IonButton,
|
|
46187
|
+
IonContent,
|
|
46188
|
+
IonIcon,
|
|
46189
|
+
ButtonComponent,
|
|
46190
|
+
DisplayComponent,
|
|
46191
|
+
TextComponent,
|
|
46192
|
+
TitleComponent,
|
|
46193
|
+
], template: `
|
|
46194
|
+
<ion-header>
|
|
46195
|
+
<ion-toolbar>
|
|
46196
|
+
<ion-buttons slot="end">
|
|
46197
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
46198
|
+
<strong>{{ resolvedCloseLabel() }}</strong>
|
|
46199
|
+
</ion-button>
|
|
46200
|
+
</ion-buttons>
|
|
46201
|
+
</ion-toolbar>
|
|
46202
|
+
</ion-header>
|
|
46203
|
+
|
|
46204
|
+
<ion-content class="ion-padding">
|
|
46205
|
+
<val-display [props]="{ content: resolvedTitle(), size: 'small', color: 'dark' }" />
|
|
46206
|
+
<val-title [props]="{ content: resolvedSubtitle(), size: 'large', color: '', bold: false }" />
|
|
46207
|
+
|
|
46208
|
+
<div class="info-features">
|
|
46209
|
+
<div class="info-feature">
|
|
46210
|
+
<ion-icon name="people-outline" class="info-feature__icon" />
|
|
46211
|
+
<div>
|
|
46212
|
+
<div class="info-feature__title">{{ tt('featureCollabTitle') }}</div>
|
|
46213
|
+
<div class="info-feature__desc">{{ tt('featureCollabDesc') }}</div>
|
|
46214
|
+
</div>
|
|
46215
|
+
</div>
|
|
46216
|
+
<div class="info-feature">
|
|
46217
|
+
<ion-icon name="swap-horizontal-outline" class="info-feature__icon" />
|
|
46218
|
+
<div>
|
|
46219
|
+
<div class="info-feature__title">{{ tt('featureSwitchTitle') }}</div>
|
|
46220
|
+
<div class="info-feature__desc">{{ tt('featureSwitchDesc') }}</div>
|
|
46221
|
+
</div>
|
|
46222
|
+
</div>
|
|
46223
|
+
<div class="info-feature">
|
|
46224
|
+
<ion-icon name="mail-outline" class="info-feature__icon" />
|
|
46225
|
+
<div>
|
|
46226
|
+
<div class="info-feature__title">{{ tt('featureInviteTitle') }}</div>
|
|
46227
|
+
<div class="info-feature__desc">{{ tt('featureInviteDesc') }}</div>
|
|
46228
|
+
</div>
|
|
46229
|
+
</div>
|
|
46230
|
+
</div>
|
|
46231
|
+
|
|
46232
|
+
@for (para of paragraphs(); track $index) {
|
|
46233
|
+
<val-text
|
|
46234
|
+
[props]="{
|
|
46235
|
+
size: 'medium',
|
|
46236
|
+
color: 'dark',
|
|
46237
|
+
bold: false,
|
|
46238
|
+
content: para,
|
|
46239
|
+
}"
|
|
46240
|
+
/>
|
|
46241
|
+
}
|
|
46242
|
+
|
|
46243
|
+
<div class="sheet-footer">
|
|
46244
|
+
<val-button [props]="resolvedCloseProps()" (click)="dismiss()" />
|
|
46245
|
+
</div>
|
|
46246
|
+
</ion-content>
|
|
46247
|
+
`, styles: ["ion-content{--padding-bottom: 32px}val-display{margin-bottom:4px;display:block}val-title{margin-bottom:8px;display:block}.info-features{display:flex;flex-direction:column;gap:12px;margin:16px 0}.info-feature{display:flex;align-items:flex-start;gap:14px;padding:12px 14px;border-radius:10px;background:var(--ion-color-light, #f4f5f8)}:host-context(body.dark) .info-feature,:host-context(html.ion-palette-dark) .info-feature,:host-context([data-theme=\"dark\"]) .info-feature{background:#ffffff0d}.info-feature__icon{font-size:22px;color:var(--ion-color-primary);flex-shrink:0;margin-top:2px}.info-feature__title{font-weight:600;font-size:.9rem;color:var(--ion-color-dark)}.info-feature__desc{font-size:.82rem;color:var(--ion-color-medium);margin-top:2px}.sheet-footer{margin-top:20px}\n"] }]
|
|
46248
|
+
}], ctorParameters: () => [], propDecorators: { title: [{
|
|
46249
|
+
type: Input
|
|
46250
|
+
}], subtitle: [{
|
|
46251
|
+
type: Input
|
|
46252
|
+
}], body: [{
|
|
46253
|
+
type: Input
|
|
46254
|
+
}], closeLabel: [{
|
|
46255
|
+
type: Input
|
|
46256
|
+
}], closeProps: [{
|
|
46257
|
+
type: Input
|
|
46258
|
+
}], _modalRef: [{
|
|
46259
|
+
type: Input
|
|
46260
|
+
}] } });
|
|
46261
|
+
|
|
46262
|
+
/**
|
|
46263
|
+
* Defaults i18n (es/en) embebidos en `val-switch-org-modal`. Auto-registrados en
|
|
46264
|
+
* el constructor del componente si el consumer no proveyó el namespace
|
|
46265
|
+
* (`Settings.SwitchOrg` por default). SOLO incluye las keys que el modal usa.
|
|
46266
|
+
*/
|
|
46267
|
+
const SWITCH_ORG_MODAL_I18N = {
|
|
46268
|
+
es: {
|
|
46269
|
+
title: 'Cambiar de cuenta',
|
|
46270
|
+
subtitle: 'Selecciona la organización a la que quieres cambiar.',
|
|
46271
|
+
searchPlaceholder: 'Buscar organización...',
|
|
46272
|
+
noResults: 'No se encontraron organizaciones.',
|
|
46273
|
+
current: 'Actual',
|
|
46274
|
+
close: 'Cerrar',
|
|
46275
|
+
switchError: 'No se pudo cambiar de organización.',
|
|
46276
|
+
},
|
|
46277
|
+
en: {
|
|
46278
|
+
title: 'Switch account',
|
|
46279
|
+
subtitle: 'Select the organization you want to switch to.',
|
|
46280
|
+
searchPlaceholder: 'Search organization...',
|
|
46281
|
+
noResults: 'No organizations found.',
|
|
46282
|
+
current: 'Active',
|
|
46283
|
+
close: 'Close',
|
|
46284
|
+
switchError: 'Could not switch organization.',
|
|
46285
|
+
},
|
|
46286
|
+
};
|
|
46287
|
+
|
|
46288
|
+
const DEFAULT_NAMESPACE$1 = 'Settings.SwitchOrg';
|
|
46289
|
+
addIcons({ businessOutline, checkmarkCircleOutline });
|
|
46290
|
+
/**
|
|
46291
|
+
* `val-switch-org-modal` — modal de cambio de organización activa (organism
|
|
46292
|
+
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
46293
|
+
* la vista Cuenta (y futuras vistas org-aware).
|
|
46294
|
+
*
|
|
46295
|
+
* Lista las organizaciones del user (vía `OrgService.listMyOrgs`), permite buscar
|
|
46296
|
+
* por nombre, y cambia la org activa con `OrgSwitchService.switchTo`. La org
|
|
46297
|
+
* actual queda primera y deshabilitada.
|
|
46298
|
+
*
|
|
46299
|
+
* Abierto vía `ModalService` — recibe `_modalRef` por `componentProps` + callback
|
|
46300
|
+
* `onSuccess`. Header canónico (Regla #5): sin `ion-title`, botón Cerrar texto en
|
|
46301
|
+
* `slot=end`, título/subtítulo en el body con `val-display`/`val-title`.
|
|
46302
|
+
*
|
|
46303
|
+
* Auto-registra sus defaults i18n (es/en) si el consumer no proveyó el namespace
|
|
46304
|
+
* `Settings.SwitchOrg`.
|
|
46305
|
+
*/
|
|
46306
|
+
class SwitchOrgModalComponent {
|
|
46307
|
+
constructor() {
|
|
46308
|
+
this.i18n = inject(I18nService);
|
|
46309
|
+
this.auth = inject(AuthService);
|
|
46310
|
+
this.orgService = inject(OrgService);
|
|
46311
|
+
this.orgSwitch = inject(OrgSwitchService);
|
|
46312
|
+
this.errors = inject(ValtechErrorService);
|
|
46313
|
+
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
46314
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$1;
|
|
46315
|
+
this.orgs = signal([]);
|
|
46316
|
+
this.loading = signal(false);
|
|
46317
|
+
this.query = signal('');
|
|
46318
|
+
this.switchingId = signal(null);
|
|
46319
|
+
this.activeOrgId = computed(() => {
|
|
46320
|
+
const u = this.auth.user();
|
|
46321
|
+
return u?.activeOrgId ?? u?.activeOrg ?? '';
|
|
46322
|
+
});
|
|
46323
|
+
this.filteredOrgs = computed(() => {
|
|
46324
|
+
const q = this.query().trim().toLowerCase();
|
|
46325
|
+
const list = this.orgs();
|
|
46326
|
+
if (!q)
|
|
46327
|
+
return list;
|
|
46328
|
+
return list.filter(o => o.name.toLowerCase().includes(q));
|
|
46329
|
+
});
|
|
46330
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$1)) {
|
|
46331
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$1, SWITCH_ORG_MODAL_I18N);
|
|
46332
|
+
}
|
|
46333
|
+
this.loadOrgs();
|
|
46334
|
+
}
|
|
46335
|
+
onQueryChange(value) {
|
|
46336
|
+
this.query.set(value ?? '');
|
|
46337
|
+
}
|
|
46338
|
+
async onSelect(org) {
|
|
46339
|
+
if (this.switchingId() || org.id === this.activeOrgId())
|
|
46340
|
+
return;
|
|
46341
|
+
this.switchingId.set(org.id);
|
|
46342
|
+
try {
|
|
46343
|
+
await this.orgSwitch.switchTo(org.id);
|
|
46344
|
+
this.onSuccess?.();
|
|
46345
|
+
this.dismiss();
|
|
46346
|
+
}
|
|
46347
|
+
catch (err) {
|
|
46348
|
+
this.errors.handle(err, {
|
|
46349
|
+
context: 'account.switchOrg',
|
|
46350
|
+
fallbackKey: 'switchError',
|
|
46351
|
+
i18nNamespace: this.i18nNamespace,
|
|
46352
|
+
});
|
|
46353
|
+
this.switchingId.set(null);
|
|
46354
|
+
}
|
|
46355
|
+
}
|
|
46356
|
+
loadOrgs() {
|
|
46357
|
+
this.loading.set(true);
|
|
46358
|
+
this.orgService
|
|
46359
|
+
.listMyOrgs()
|
|
46360
|
+
.pipe(take(1))
|
|
46361
|
+
.subscribe({
|
|
46362
|
+
next: orgs => {
|
|
46363
|
+
const activeId = this.activeOrgId();
|
|
46364
|
+
this.orgs.set([...orgs].sort((a, b) => (a.id === activeId ? -1 : b.id === activeId ? 1 : 0)));
|
|
46365
|
+
this.loading.set(false);
|
|
46366
|
+
},
|
|
46367
|
+
error: () => this.loading.set(false),
|
|
46368
|
+
});
|
|
46369
|
+
}
|
|
46370
|
+
dismiss() {
|
|
46371
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
46372
|
+
}
|
|
46373
|
+
t(key) {
|
|
46374
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
46375
|
+
}
|
|
46376
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SwitchOrgModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46377
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SwitchOrgModalComponent, isStandalone: true, selector: "val-switch-org-modal", inputs: { _modalRef: "_modalRef", onSuccess: "onSuccess", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
46378
|
+
<ion-header>
|
|
46379
|
+
<ion-toolbar>
|
|
46380
|
+
<ion-buttons slot="end">
|
|
46381
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
46382
|
+
<strong>{{ t('close') }}</strong>
|
|
46383
|
+
</ion-button>
|
|
46384
|
+
</ion-buttons>
|
|
46385
|
+
</ion-toolbar>
|
|
46386
|
+
</ion-header>
|
|
46387
|
+
|
|
46388
|
+
<ion-content class="ion-padding">
|
|
46389
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
46390
|
+
<val-title
|
|
46391
|
+
[props]="{
|
|
46392
|
+
content: t('subtitle'),
|
|
46393
|
+
size: 'large',
|
|
46394
|
+
color: '',
|
|
46395
|
+
bold: false,
|
|
46396
|
+
}"
|
|
46397
|
+
/>
|
|
46398
|
+
|
|
46399
|
+
<div class="switch-section">
|
|
46400
|
+
<val-searchbar
|
|
46401
|
+
[props]="{
|
|
46402
|
+
placeholder: t('searchPlaceholder'),
|
|
46403
|
+
debounce: 200,
|
|
46404
|
+
showCancelButton: 'never',
|
|
46405
|
+
}"
|
|
46406
|
+
(filterEvent)="onQueryChange($event)"
|
|
46407
|
+
/>
|
|
46408
|
+
|
|
46409
|
+
@if (loading()) {
|
|
46410
|
+
<div class="switch-state">
|
|
46411
|
+
<ion-spinner name="crescent" />
|
|
46412
|
+
</div>
|
|
46413
|
+
} @else if (filteredOrgs().length === 0) {
|
|
46414
|
+
<val-empty-state
|
|
46415
|
+
[props]="{
|
|
46416
|
+
variant: 'empty',
|
|
46417
|
+
title: t('noResults'),
|
|
46418
|
+
icon: 'business-outline',
|
|
46419
|
+
}"
|
|
46420
|
+
/>
|
|
46421
|
+
} @else {
|
|
46422
|
+
<div class="orgs-list">
|
|
46423
|
+
@for (org of filteredOrgs(); track org.id) {
|
|
46424
|
+
<button
|
|
46425
|
+
type="button"
|
|
46426
|
+
class="org-row"
|
|
46427
|
+
[class.org-row--active]="org.id === activeOrgId()"
|
|
46428
|
+
[disabled]="!!switchingId() || org.id === activeOrgId()"
|
|
46429
|
+
(click)="onSelect(org)"
|
|
46430
|
+
>
|
|
46431
|
+
<div class="org-row__icon">
|
|
46432
|
+
<ion-icon name="business-outline" />
|
|
46433
|
+
</div>
|
|
46434
|
+
<div class="org-row__body">
|
|
46435
|
+
<span class="org-row__name">{{ org.name }}</span>
|
|
46436
|
+
<span class="org-row__type">{{ org.type }}</span>
|
|
46437
|
+
</div>
|
|
46438
|
+
<div class="org-row__end">
|
|
46439
|
+
@if (switchingId() === org.id) {
|
|
46440
|
+
<ion-spinner name="crescent" class="org-row__spinner" />
|
|
46441
|
+
} @else if (org.id === activeOrgId()) {
|
|
46442
|
+
<span class="org-row__current">{{ t('current') }}</span>
|
|
46443
|
+
<ion-icon name="checkmark-circle-outline" class="org-row__check" />
|
|
46444
|
+
}
|
|
46445
|
+
</div>
|
|
46446
|
+
</button>
|
|
46447
|
+
}
|
|
46448
|
+
</div>
|
|
46449
|
+
}
|
|
46450
|
+
</div>
|
|
46451
|
+
</ion-content>
|
|
46452
|
+
`, isInline: true, styles: [".switch-section{margin-top:16px;display:flex;flex-direction:column;gap:12px}.switch-state{display:flex;justify-content:center;padding:24px 0}.orgs-list{display:flex;flex-direction:column;gap:8px}.org-row{display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;border:1px solid rgba(var(--ion-color-dark-rgb),.14);border-radius:12px;background:var(--ion-card-background, var(--ion-background-color));cursor:pointer;text-align:left;transition:border-color .15s ease,opacity .15s ease}.org-row:not(:disabled):active{opacity:.7}.org-row:disabled{cursor:default}.org-row--active{border-color:var(--ion-color-dark)}.org-row__icon{width:36px;height:36px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:18px;color:var(--ion-color-dark);background:rgba(var(--ion-color-dark-rgb),.08)}.org-row__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.org-row__name{font-weight:600;font-size:.95rem;color:var(--ion-color-dark);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.org-row__type{font-size:.8rem;color:rgba(var(--ion-color-dark-rgb),.7)}.org-row__end{display:flex;align-items:center;gap:6px;flex-shrink:0}.org-row__current{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:rgba(var(--ion-color-dark-rgb),.7)}.org-row__check{font-size:1.1rem;color:var(--ion-color-dark)}.org-row__spinner{width:18px;height:18px;color:var(--ion-color-dark)}\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: "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: TitleComponent, selector: "val-title", inputs: ["props"] }] }); }
|
|
46453
|
+
}
|
|
46454
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SwitchOrgModalComponent, decorators: [{
|
|
46455
|
+
type: Component,
|
|
46456
|
+
args: [{ selector: 'val-switch-org-modal', standalone: true, imports: [
|
|
46457
|
+
IonHeader,
|
|
46458
|
+
IonToolbar,
|
|
46459
|
+
IonButtons,
|
|
46460
|
+
IonButton,
|
|
46461
|
+
IonContent,
|
|
46462
|
+
IonSpinner,
|
|
46463
|
+
IonIcon,
|
|
46464
|
+
DisplayComponent,
|
|
46465
|
+
EmptyStateComponent,
|
|
46466
|
+
SearchbarComponent,
|
|
46467
|
+
TitleComponent,
|
|
46468
|
+
], template: `
|
|
46469
|
+
<ion-header>
|
|
46470
|
+
<ion-toolbar>
|
|
46471
|
+
<ion-buttons slot="end">
|
|
46472
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
46473
|
+
<strong>{{ t('close') }}</strong>
|
|
46474
|
+
</ion-button>
|
|
46475
|
+
</ion-buttons>
|
|
46476
|
+
</ion-toolbar>
|
|
46477
|
+
</ion-header>
|
|
46478
|
+
|
|
46479
|
+
<ion-content class="ion-padding">
|
|
46480
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
46481
|
+
<val-title
|
|
46482
|
+
[props]="{
|
|
46483
|
+
content: t('subtitle'),
|
|
46484
|
+
size: 'large',
|
|
46485
|
+
color: '',
|
|
46486
|
+
bold: false,
|
|
46487
|
+
}"
|
|
46488
|
+
/>
|
|
46489
|
+
|
|
46490
|
+
<div class="switch-section">
|
|
46491
|
+
<val-searchbar
|
|
46492
|
+
[props]="{
|
|
46493
|
+
placeholder: t('searchPlaceholder'),
|
|
46494
|
+
debounce: 200,
|
|
46495
|
+
showCancelButton: 'never',
|
|
46496
|
+
}"
|
|
46497
|
+
(filterEvent)="onQueryChange($event)"
|
|
46498
|
+
/>
|
|
46499
|
+
|
|
46500
|
+
@if (loading()) {
|
|
46501
|
+
<div class="switch-state">
|
|
46502
|
+
<ion-spinner name="crescent" />
|
|
46503
|
+
</div>
|
|
46504
|
+
} @else if (filteredOrgs().length === 0) {
|
|
46505
|
+
<val-empty-state
|
|
46506
|
+
[props]="{
|
|
46507
|
+
variant: 'empty',
|
|
46508
|
+
title: t('noResults'),
|
|
46509
|
+
icon: 'business-outline',
|
|
46510
|
+
}"
|
|
46511
|
+
/>
|
|
46512
|
+
} @else {
|
|
46513
|
+
<div class="orgs-list">
|
|
46514
|
+
@for (org of filteredOrgs(); track org.id) {
|
|
46515
|
+
<button
|
|
46516
|
+
type="button"
|
|
46517
|
+
class="org-row"
|
|
46518
|
+
[class.org-row--active]="org.id === activeOrgId()"
|
|
46519
|
+
[disabled]="!!switchingId() || org.id === activeOrgId()"
|
|
46520
|
+
(click)="onSelect(org)"
|
|
46521
|
+
>
|
|
46522
|
+
<div class="org-row__icon">
|
|
46523
|
+
<ion-icon name="business-outline" />
|
|
46524
|
+
</div>
|
|
46525
|
+
<div class="org-row__body">
|
|
46526
|
+
<span class="org-row__name">{{ org.name }}</span>
|
|
46527
|
+
<span class="org-row__type">{{ org.type }}</span>
|
|
46528
|
+
</div>
|
|
46529
|
+
<div class="org-row__end">
|
|
46530
|
+
@if (switchingId() === org.id) {
|
|
46531
|
+
<ion-spinner name="crescent" class="org-row__spinner" />
|
|
46532
|
+
} @else if (org.id === activeOrgId()) {
|
|
46533
|
+
<span class="org-row__current">{{ t('current') }}</span>
|
|
46534
|
+
<ion-icon name="checkmark-circle-outline" class="org-row__check" />
|
|
46535
|
+
}
|
|
46536
|
+
</div>
|
|
46537
|
+
</button>
|
|
46538
|
+
}
|
|
46539
|
+
</div>
|
|
46540
|
+
}
|
|
46541
|
+
</div>
|
|
46542
|
+
</ion-content>
|
|
46543
|
+
`, styles: [".switch-section{margin-top:16px;display:flex;flex-direction:column;gap:12px}.switch-state{display:flex;justify-content:center;padding:24px 0}.orgs-list{display:flex;flex-direction:column;gap:8px}.org-row{display:flex;align-items:center;gap:12px;width:100%;padding:12px 14px;border:1px solid rgba(var(--ion-color-dark-rgb),.14);border-radius:12px;background:var(--ion-card-background, var(--ion-background-color));cursor:pointer;text-align:left;transition:border-color .15s ease,opacity .15s ease}.org-row:not(:disabled):active{opacity:.7}.org-row:disabled{cursor:default}.org-row--active{border-color:var(--ion-color-dark)}.org-row__icon{width:36px;height:36px;border-radius:50%;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:18px;color:var(--ion-color-dark);background:rgba(var(--ion-color-dark-rgb),.08)}.org-row__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.org-row__name{font-weight:600;font-size:.95rem;color:var(--ion-color-dark);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.org-row__type{font-size:.8rem;color:rgba(var(--ion-color-dark-rgb),.7)}.org-row__end{display:flex;align-items:center;gap:6px;flex-shrink:0}.org-row__current{font-size:.74rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:rgba(var(--ion-color-dark-rgb),.7)}.org-row__check{font-size:1.1rem;color:var(--ion-color-dark)}.org-row__spinner{width:18px;height:18px;color:var(--ion-color-dark)}\n"] }]
|
|
46544
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
46545
|
+
type: Input
|
|
46546
|
+
}], onSuccess: [{
|
|
46547
|
+
type: Input
|
|
46548
|
+
}], i18nNamespace: [{
|
|
46549
|
+
type: Input
|
|
46550
|
+
}] } });
|
|
46551
|
+
|
|
46552
|
+
/**
|
|
46553
|
+
* Defaults i18n (es/en) embebidos en `val-account-view`. Auto-registrados en el
|
|
46554
|
+
* constructor del componente si el consumer no proveyó el namespace
|
|
46555
|
+
* (`Settings.Account` por default). SOLO incluye las keys que la vista usa.
|
|
46556
|
+
*/
|
|
46557
|
+
const ACCOUNT_VIEW_I18N = {
|
|
46558
|
+
es: {
|
|
46559
|
+
pageTitle: 'Cuenta',
|
|
46560
|
+
pageDescription: 'Organizaciones y seguridad de la cuenta',
|
|
46561
|
+
orgsTitle: 'Tus organizaciones',
|
|
46562
|
+
orgsCurrent: 'Actual',
|
|
46563
|
+
orgsEmpty: 'Aún no perteneces a otras organizaciones.',
|
|
46564
|
+
orgsSwitch: 'Cambiar',
|
|
46565
|
+
switchAccountCta: 'Cambiar de cuenta',
|
|
46566
|
+
orgsViewAll: 'Ver todas',
|
|
46567
|
+
orgsManage: 'Gestionar',
|
|
46568
|
+
orgsEmptyHint: 'Aún no perteneces a otras organizaciones.',
|
|
46569
|
+
orgsNewCta: 'Nueva organización',
|
|
46570
|
+
orgsNewQuestion: '¿Necesitas otra organización?',
|
|
46571
|
+
orgsNewHint: 'Crea un espacio separado para otro equipo, empresa o proyecto.',
|
|
46572
|
+
orgsMoreInfo: 'Más información',
|
|
46573
|
+
orgsInfoTitle: '¿Qué son las organizaciones?',
|
|
46574
|
+
orgsInfoSubtitle: 'Todo lo que necesitas saber',
|
|
46575
|
+
orgsInfoClose: 'Cerrar',
|
|
46576
|
+
orgsInfoContent: 'Las organizaciones te permiten separar tus proyectos y datos por empresa, equipo o contexto. Puedes pertenecer a varias organizaciones y cambiar entre ellas en cualquier momento.\n\nCada organización tiene sus propios miembros, roles y permisos. La organización activa determina qué datos ves y qué acciones puedes realizar.\n\nPuedes crear una organización nueva o unirte a una existente mediante invitación.',
|
|
46577
|
+
orgsTypePersonal: 'Personal',
|
|
46578
|
+
orgsTypePrivate: 'Privada',
|
|
46579
|
+
orgsTypePublic: 'Pública',
|
|
46580
|
+
orgsTypeBusiness: 'Empresa',
|
|
46581
|
+
orgsLabelType: 'Tipo',
|
|
46582
|
+
orgsLabelRole: 'Rol',
|
|
46583
|
+
orgsLabelStatus: 'Estado',
|
|
46584
|
+
orgsStatusActive: 'Activa',
|
|
46585
|
+
logoutTitle: 'Cerrar esta sesión',
|
|
46586
|
+
logoutHint: 'Cierra tu sesión en este dispositivo.',
|
|
46587
|
+
logout: 'Cerrar sesión',
|
|
46588
|
+
dangerTitle: 'Zona peligrosa',
|
|
46589
|
+
dangerDeleteTitle: 'Eliminar cuenta',
|
|
46590
|
+
dangerDeleteHint: 'Borra tu cuenta y todos los datos asociados. Esta acción no se puede deshacer.',
|
|
46591
|
+
dangerDeleteCta: 'Eliminar cuenta',
|
|
46592
|
+
inviteAccepted: 'Te has unido a la organización.',
|
|
46593
|
+
inviteDeclined: 'Invitación rechazada.',
|
|
46594
|
+
accept: 'Aceptar',
|
|
46595
|
+
decline: 'Rechazar',
|
|
46596
|
+
pendingInvitesTitle: 'Invitaciones pendientes',
|
|
46597
|
+
orgsErrorTitle: 'No se pudieron cargar las organizaciones',
|
|
46598
|
+
orgsOfflineTitle: 'Sin conexión',
|
|
46599
|
+
orgsOfflineHint: 'Verifica tu conexión e intenta de nuevo.',
|
|
46600
|
+
orgsRetry: 'Reintentar',
|
|
46601
|
+
},
|
|
46602
|
+
en: {
|
|
46603
|
+
pageTitle: 'Account',
|
|
46604
|
+
pageDescription: 'Organizations and account security',
|
|
46605
|
+
orgsTitle: 'Your organizations',
|
|
46606
|
+
orgsCurrent: 'Active',
|
|
46607
|
+
orgsEmpty: "You don't belong to other organizations yet.",
|
|
46608
|
+
orgsSwitch: 'Switch',
|
|
46609
|
+
switchAccountCta: 'Switch account',
|
|
46610
|
+
orgsViewAll: 'View all',
|
|
46611
|
+
orgsManage: 'Manage',
|
|
46612
|
+
orgsEmptyHint: "You don't belong to other organizations yet.",
|
|
46613
|
+
orgsNewCta: 'New organization',
|
|
46614
|
+
orgsNewQuestion: 'Need another organization?',
|
|
46615
|
+
orgsNewHint: 'Create a separate space for another team, company or project.',
|
|
46616
|
+
orgsMoreInfo: 'More information',
|
|
46617
|
+
orgsInfoTitle: 'What are organizations?',
|
|
46618
|
+
orgsInfoSubtitle: 'Everything you need to know',
|
|
46619
|
+
orgsInfoClose: 'Close',
|
|
46620
|
+
orgsInfoContent: 'Organizations let you separate your projects and data by company, team, or context. You can belong to multiple organizations and switch between them at any time.\n\nEach organization has its own members, roles, and permissions. The active organization determines what data you see and what actions you can take.\n\nYou can create a new organization or join an existing one via invitation.',
|
|
46621
|
+
orgsTypePersonal: 'Personal',
|
|
46622
|
+
orgsTypePrivate: 'Private',
|
|
46623
|
+
orgsTypePublic: 'Public',
|
|
46624
|
+
orgsTypeBusiness: 'Business',
|
|
46625
|
+
orgsLabelType: 'Type',
|
|
46626
|
+
orgsLabelRole: 'Role',
|
|
46627
|
+
orgsLabelStatus: 'Status',
|
|
46628
|
+
orgsStatusActive: 'Active',
|
|
46629
|
+
logoutTitle: 'Sign out of this device',
|
|
46630
|
+
logoutHint: 'End your session on this device.',
|
|
46631
|
+
logout: 'Sign out',
|
|
46632
|
+
dangerTitle: 'Danger zone',
|
|
46633
|
+
dangerDeleteTitle: 'Delete account',
|
|
46634
|
+
dangerDeleteHint: 'Delete your account and all related data. This action cannot be undone.',
|
|
46635
|
+
dangerDeleteCta: 'Delete account',
|
|
46636
|
+
inviteAccepted: 'You have joined the organization.',
|
|
46637
|
+
inviteDeclined: 'Invitation declined.',
|
|
46638
|
+
accept: 'Accept',
|
|
46639
|
+
decline: 'Decline',
|
|
46640
|
+
pendingInvitesTitle: 'Pending invitations',
|
|
46641
|
+
orgsErrorTitle: 'Could not load organizations',
|
|
46642
|
+
orgsOfflineTitle: 'No connection',
|
|
46643
|
+
orgsOfflineHint: 'Check your connection and try again.',
|
|
46644
|
+
orgsRetry: 'Retry',
|
|
46645
|
+
},
|
|
46646
|
+
};
|
|
46647
|
+
|
|
46648
|
+
addIcons({ peopleOutline, businessOutline, chevronForwardOutline, swapHorizontalOutline, mailOutline });
|
|
46649
|
+
const DEFAULT_NAMESPACE = 'Settings.Account';
|
|
46650
|
+
const DEFAULT_MANAGE_ORG_ROUTE = '/app/settings/organization';
|
|
46651
|
+
/**
|
|
46652
|
+
* `val-account-view` — vista Cuenta full-feature autocontenida (organism).
|
|
46653
|
+
* Promovida desde `showcase` bajo el proceso de ADR-021. Reúne:
|
|
46654
|
+
* - **Invitaciones pendientes** — aceptar / rechazar (`val-invitation-card`).
|
|
46655
|
+
* - **Organizaciones** — card de org activa + empty-card + CTA "Nueva org"
|
|
46656
|
+
* (modal `val-create-org-modal`) + "Ver todas" (modal `val-switch-org-modal`).
|
|
46657
|
+
* - **Cerrar esta sesión** — `auth.logoutWithConfirmation()`.
|
|
46658
|
+
* - **Eliminar cuenta** — modal `val-delete-account-modal`.
|
|
46659
|
+
*
|
|
46660
|
+
* NO renderiza ion-content — vive dentro de val-page-wrapper. No usa deep-links;
|
|
46661
|
+
* `ActivatedRoute` se inyecta `{ optional: true }` solo para leer el route data
|
|
46662
|
+
* de config. La navegación a la org route va por `NavigationService`.
|
|
46663
|
+
*
|
|
46664
|
+
* Auto-registra sus defaults i18n (es/en) en el constructor si el consumer no
|
|
46665
|
+
* proveyó el namespace configurado (default `Settings.Account`).
|
|
46666
|
+
*/
|
|
46667
|
+
class AccountViewComponent {
|
|
46668
|
+
/** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
|
|
46669
|
+
get ns() {
|
|
46670
|
+
return this.resolvedConfig().i18nNamespace;
|
|
46671
|
+
}
|
|
46672
|
+
constructor() {
|
|
46673
|
+
this.nav = inject(NavigationService);
|
|
46674
|
+
this.i18n = inject(I18nService);
|
|
46675
|
+
this.auth = inject(AuthService);
|
|
46676
|
+
this.orgService = inject(OrgService);
|
|
46677
|
+
this.modalService = inject(ModalService);
|
|
46678
|
+
this.toast = inject(ToastService);
|
|
46679
|
+
this.errors = inject(ValtechErrorService);
|
|
46680
|
+
this.route = inject(ActivatedRoute, { optional: true });
|
|
46681
|
+
this.resolvedConfig = computed(() => {
|
|
46682
|
+
const fromRoute = (this.route?.snapshot.data['accountConfig'] ?? {});
|
|
46683
|
+
const merged = { ...fromRoute, ...(this.config ?? {}) };
|
|
46684
|
+
return {
|
|
46685
|
+
showPendingInvites: merged.showPendingInvites ?? true,
|
|
46686
|
+
showOrganizations: merged.showOrganizations ?? true,
|
|
46687
|
+
showNewOrgCta: merged.showNewOrgCta ?? true,
|
|
46688
|
+
showLogout: merged.showLogout ?? true,
|
|
46689
|
+
showDeleteAccount: merged.showDeleteAccount ?? true,
|
|
46690
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
46691
|
+
manageOrgRoute: merged.manageOrgRoute ?? DEFAULT_MANAGE_ORG_ROUTE,
|
|
46692
|
+
onOrgSwitched: merged.onOrgSwitched,
|
|
46693
|
+
onOrgCreated: merged.onOrgCreated,
|
|
46694
|
+
onLoggedOut: merged.onLoggedOut,
|
|
46695
|
+
onAccountDeleted: merged.onAccountDeleted,
|
|
46696
|
+
};
|
|
46697
|
+
});
|
|
46698
|
+
this.orgs = signal([]);
|
|
46699
|
+
this.orgsLoading = signal(false);
|
|
46700
|
+
this.orgsError = signal(null);
|
|
46701
|
+
this.orgsErrorState = computed(() => {
|
|
46702
|
+
this.i18n.lang();
|
|
46703
|
+
const err = this.orgsError();
|
|
46704
|
+
if (!err)
|
|
46705
|
+
return null;
|
|
46706
|
+
return createErrorStateProps(err, {
|
|
46707
|
+
title: {
|
|
46708
|
+
offline: this.tt('orgsOfflineTitle'),
|
|
46709
|
+
error: this.tt('orgsErrorTitle'),
|
|
46710
|
+
},
|
|
46711
|
+
description: {
|
|
46712
|
+
offline: this.tt('orgsOfflineHint'),
|
|
46713
|
+
error: interpretError(err).message,
|
|
46714
|
+
},
|
|
46715
|
+
retryLabel: this.tt('orgsRetry'),
|
|
46716
|
+
onRetry: () => this.loadOrgs(),
|
|
46717
|
+
retrying: this.orgsLoading(),
|
|
46718
|
+
});
|
|
46719
|
+
});
|
|
46720
|
+
this.pendingInvites = signal([]);
|
|
46721
|
+
this.pendingInvitesLoading = signal(false);
|
|
46722
|
+
this.inviteAccepting = signal(null);
|
|
46723
|
+
this.pageTitle = computed(() => this.tt('pageTitle'));
|
|
46724
|
+
this.pageDescription = computed(() => this.tt('pageDescription'));
|
|
46725
|
+
this.orgsTitle = computed(() => this.tt('orgsTitle'));
|
|
46726
|
+
this.orgsEmpty = computed(() => this.tt('orgsEmpty'));
|
|
46727
|
+
this.orgsMoreInfo = computed(() => this.tt('orgsMoreInfo'));
|
|
46728
|
+
this.orgsNewQuestion = computed(() => this.tt('orgsNewQuestion'));
|
|
46729
|
+
this.orgsNewHint = computed(() => this.tt('orgsNewHint'));
|
|
46730
|
+
this.newOrgCtaProps = computed(() => ({
|
|
46731
|
+
title: this.tt('orgsNewQuestion'),
|
|
46732
|
+
description: this.tt('orgsNewHint'),
|
|
46733
|
+
padding: '16px',
|
|
46734
|
+
borderRadius: '14px',
|
|
46735
|
+
actions: {
|
|
46736
|
+
position: 'right',
|
|
46737
|
+
columned: false,
|
|
46738
|
+
buttons: [
|
|
46739
|
+
{
|
|
46740
|
+
text: this.tt('orgsNewCta'),
|
|
46741
|
+
color: 'primary',
|
|
46742
|
+
fill: 'outline',
|
|
46743
|
+
shape: 'round',
|
|
46744
|
+
size: 'default',
|
|
46745
|
+
type: 'button',
|
|
46746
|
+
state: 'ENABLED',
|
|
46747
|
+
token: 'account-new-org',
|
|
46748
|
+
},
|
|
46749
|
+
],
|
|
46750
|
+
},
|
|
46751
|
+
}));
|
|
46752
|
+
this.logoutTitle = computed(() => this.tt('logoutTitle'));
|
|
46753
|
+
this.logoutHint = computed(() => this.tt('logoutHint'));
|
|
46754
|
+
this.dangerTitle = computed(() => this.tt('dangerTitle'));
|
|
46755
|
+
this.dangerDeleteTitle = computed(() => this.tt('dangerDeleteTitle'));
|
|
46756
|
+
this.dangerDeleteHint = computed(() => this.tt('dangerDeleteHint'));
|
|
46757
|
+
this.activeOrgId = computed(() => {
|
|
46758
|
+
const u = this.auth.user();
|
|
46759
|
+
return u?.activeOrgId ?? u?.activeOrg ?? '';
|
|
46760
|
+
});
|
|
46761
|
+
this.activeOrgRole = computed(() => {
|
|
46762
|
+
const roles = this.auth.roles?.() ?? [];
|
|
46763
|
+
return roles[0] ?? null;
|
|
46764
|
+
});
|
|
46765
|
+
this.activeOrg = computed(() => this.orgs().find(o => o.id === this.activeOrgId()) ?? null);
|
|
46766
|
+
this.logoutButtonProps = computed(() => ({
|
|
46767
|
+
text: this.tt('logout'),
|
|
46768
|
+
color: 'dark',
|
|
46769
|
+
fill: 'outline',
|
|
46770
|
+
size: 'default',
|
|
46771
|
+
shape: 'round',
|
|
46772
|
+
type: 'button',
|
|
46773
|
+
token: 'account-logout',
|
|
46774
|
+
}));
|
|
46775
|
+
this.deleteAccountButtonProps = computed(() => ({
|
|
46776
|
+
text: this.tt('dangerDeleteCta'),
|
|
46777
|
+
color: 'dark',
|
|
46778
|
+
fill: 'outline',
|
|
46779
|
+
size: 'default',
|
|
46780
|
+
shape: 'round',
|
|
46781
|
+
type: 'button',
|
|
46782
|
+
token: 'account-delete',
|
|
46783
|
+
}));
|
|
46784
|
+
this.switchAccountButtonProps = computed(() => ({
|
|
46785
|
+
text: this.tt('switchAccountCta'),
|
|
46786
|
+
color: 'dark',
|
|
46787
|
+
fill: 'outline',
|
|
46788
|
+
size: 'default',
|
|
46789
|
+
shape: 'round',
|
|
46790
|
+
type: 'button',
|
|
46791
|
+
token: 'account-switch',
|
|
46792
|
+
}));
|
|
46793
|
+
const ns = this.ns;
|
|
46794
|
+
if (!this.i18n.hasNamespace(ns)) {
|
|
46795
|
+
this.i18n.registerContent(ns, ACCOUNT_VIEW_I18N);
|
|
46796
|
+
}
|
|
46797
|
+
this.nav.setBackHeader('pageTitle', ns, { withMenu: true });
|
|
46798
|
+
this.loadOrgs();
|
|
46799
|
+
this.loadPendingInvites();
|
|
46800
|
+
connectPageRefresh(async () => {
|
|
46801
|
+
await Promise.all([this.loadOrgs(), this.loadPendingInvites()]);
|
|
46802
|
+
});
|
|
46803
|
+
}
|
|
46804
|
+
orgTypeLabel(type) {
|
|
46805
|
+
const map = {
|
|
46806
|
+
PERSONAL: this.tt('orgsTypePersonal'),
|
|
46807
|
+
PRIVATE: this.tt('orgsTypePrivate'),
|
|
46808
|
+
PUBLIC: this.tt('orgsTypePublic'),
|
|
46809
|
+
BUSINESS: this.tt('orgsTypeBusiness'),
|
|
46810
|
+
};
|
|
46811
|
+
return map[type] ?? type;
|
|
46812
|
+
}
|
|
46813
|
+
onSwitchAccount() {
|
|
46814
|
+
void this.modalService.open({
|
|
46815
|
+
component: SwitchOrgModalComponent,
|
|
46816
|
+
componentProps: {
|
|
46817
|
+
i18nNamespace: 'Settings.SwitchOrg',
|
|
46818
|
+
onSuccess: () => {
|
|
46819
|
+
this.loadOrgs();
|
|
46820
|
+
this.loadPendingInvites();
|
|
46821
|
+
this.resolvedConfig().onOrgSwitched?.();
|
|
46822
|
+
},
|
|
46823
|
+
},
|
|
46824
|
+
breakpoints: {
|
|
46825
|
+
breakpoints: [0, 0.85],
|
|
46826
|
+
initialBreakpoint: 0.85,
|
|
46827
|
+
showHandle: true,
|
|
46828
|
+
},
|
|
46829
|
+
backdropDismiss: true,
|
|
46830
|
+
});
|
|
46831
|
+
}
|
|
46832
|
+
onDeleteAccount() {
|
|
46833
|
+
void this.modalService.open({
|
|
46834
|
+
component: DeleteAccountModalComponent,
|
|
46835
|
+
componentProps: {
|
|
46836
|
+
i18nNamespace: 'Settings.DeleteAccount',
|
|
46837
|
+
},
|
|
46838
|
+
breakpoints: {
|
|
46839
|
+
breakpoints: [0, 0.85],
|
|
46840
|
+
initialBreakpoint: 0.85,
|
|
46841
|
+
showHandle: true,
|
|
46842
|
+
},
|
|
46843
|
+
backdropDismiss: false,
|
|
46844
|
+
});
|
|
46845
|
+
this.resolvedConfig().onAccountDeleted?.();
|
|
46846
|
+
}
|
|
46847
|
+
onManageOrg() {
|
|
46848
|
+
this.nav.navigateByUrl(this.resolvedConfig().manageOrgRoute);
|
|
46849
|
+
}
|
|
46850
|
+
onNewOrg() {
|
|
46851
|
+
void this.modalService.open({
|
|
46852
|
+
component: CreateOrgModalComponent,
|
|
46853
|
+
componentProps: {
|
|
46854
|
+
i18nNamespace: 'CreateOrgModal',
|
|
46855
|
+
onSuccess: (newOrg) => {
|
|
46856
|
+
this.loadOrgs();
|
|
46857
|
+
this.resolvedConfig().onOrgCreated?.(newOrg);
|
|
46858
|
+
},
|
|
46859
|
+
},
|
|
46860
|
+
breakpoints: {
|
|
46861
|
+
breakpoints: [0, 0.92],
|
|
46862
|
+
initialBreakpoint: 0.92,
|
|
46863
|
+
showHandle: true,
|
|
46864
|
+
},
|
|
46865
|
+
backdropDismiss: true,
|
|
46866
|
+
});
|
|
46867
|
+
}
|
|
46868
|
+
onMoreInfo() {
|
|
46869
|
+
void this.modalService.open({
|
|
46870
|
+
component: OrgInfoSheetComponent,
|
|
46871
|
+
componentProps: {
|
|
46872
|
+
title: this.tt('orgsInfoTitle'),
|
|
46873
|
+
subtitle: this.tt('orgsInfoSubtitle'),
|
|
46874
|
+
body: this.tt('orgsInfoContent'),
|
|
46875
|
+
closeLabel: this.tt('orgsInfoClose'),
|
|
46876
|
+
closeProps: {
|
|
46877
|
+
text: this.tt('orgsInfoClose'),
|
|
46878
|
+
fill: 'outline',
|
|
46879
|
+
color: 'dark',
|
|
46880
|
+
size: 'default',
|
|
46881
|
+
expand: 'block',
|
|
46882
|
+
type: 'button',
|
|
46883
|
+
},
|
|
46884
|
+
},
|
|
46885
|
+
breakpoints: {
|
|
46886
|
+
breakpoints: [0, 0.85],
|
|
46887
|
+
initialBreakpoint: 0.85,
|
|
46888
|
+
showHandle: true,
|
|
46889
|
+
},
|
|
46890
|
+
backdropDismiss: true,
|
|
46891
|
+
});
|
|
46892
|
+
}
|
|
46893
|
+
onLogout() {
|
|
46894
|
+
this.auth.logoutWithConfirmation();
|
|
46895
|
+
this.resolvedConfig().onLoggedOut?.();
|
|
46896
|
+
}
|
|
46897
|
+
loadPendingInvites() {
|
|
46898
|
+
this.pendingInvitesLoading.set(true);
|
|
46899
|
+
return new Promise(resolve => {
|
|
46900
|
+
this.orgService
|
|
46901
|
+
.getPendingInvitations()
|
|
46902
|
+
.pipe(take(1))
|
|
46903
|
+
.subscribe({
|
|
46904
|
+
next: items => {
|
|
46905
|
+
this.pendingInvites.set(items);
|
|
46906
|
+
this.pendingInvitesLoading.set(false);
|
|
46907
|
+
resolve();
|
|
46908
|
+
},
|
|
46909
|
+
error: () => {
|
|
46910
|
+
this.pendingInvitesLoading.set(false);
|
|
46911
|
+
resolve();
|
|
46912
|
+
},
|
|
46913
|
+
});
|
|
46914
|
+
});
|
|
46915
|
+
}
|
|
46916
|
+
acceptPendingInvite(invite) {
|
|
46917
|
+
if (this.inviteAccepting())
|
|
46918
|
+
return;
|
|
46919
|
+
this.inviteAccepting.set(invite.orgId);
|
|
46920
|
+
this.orgService
|
|
46921
|
+
.acceptInvitation(invite.orgId)
|
|
46922
|
+
.pipe(take(1))
|
|
46923
|
+
.subscribe({
|
|
46924
|
+
next: () => {
|
|
46925
|
+
this.toast.show({
|
|
46926
|
+
message: this.tt('inviteAccepted'),
|
|
46927
|
+
color: 'dark',
|
|
46928
|
+
duration: 3500,
|
|
46929
|
+
});
|
|
46930
|
+
this.pendingInvites.update(list => list.filter(i => i.orgId !== invite.orgId));
|
|
46931
|
+
this.loadOrgs();
|
|
46932
|
+
},
|
|
46933
|
+
error: err => {
|
|
46934
|
+
this.errors.handle(err, { context: 'account.acceptPendingInvite' });
|
|
46935
|
+
this.inviteAccepting.set(null);
|
|
46936
|
+
},
|
|
46937
|
+
complete: () => this.inviteAccepting.set(null),
|
|
46938
|
+
});
|
|
46939
|
+
}
|
|
46940
|
+
declinePendingInvite(invite) {
|
|
46941
|
+
if (this.inviteAccepting())
|
|
46942
|
+
return;
|
|
46943
|
+
this.inviteAccepting.set(invite.orgId);
|
|
46944
|
+
this.orgService
|
|
46945
|
+
.declineInvitation(invite.orgId)
|
|
46946
|
+
.pipe(take(1))
|
|
46947
|
+
.subscribe({
|
|
46948
|
+
next: () => {
|
|
46949
|
+
this.toast.show({
|
|
46950
|
+
message: this.tt('inviteDeclined'),
|
|
46951
|
+
color: 'dark',
|
|
46952
|
+
duration: 2500,
|
|
46953
|
+
});
|
|
46954
|
+
this.pendingInvites.update(list => list.filter(i => i.orgId !== invite.orgId));
|
|
46955
|
+
},
|
|
46956
|
+
error: err => {
|
|
46957
|
+
this.errors.handle(err, { context: 'account.declinePendingInvite' });
|
|
46958
|
+
this.inviteAccepting.set(null);
|
|
46959
|
+
},
|
|
46960
|
+
complete: () => this.inviteAccepting.set(null),
|
|
46961
|
+
});
|
|
46962
|
+
}
|
|
46963
|
+
loadOrgs() {
|
|
46964
|
+
this.orgsLoading.set(true);
|
|
46965
|
+
this.orgsError.set(null);
|
|
46966
|
+
return new Promise(resolve => {
|
|
46967
|
+
this.orgService.listMyOrgs().subscribe({
|
|
46968
|
+
next: orgs => {
|
|
46969
|
+
const activeId = this.activeOrgId();
|
|
46970
|
+
this.orgs.set([...orgs].sort((a, b) => (a.id === activeId ? -1 : b.id === activeId ? 1 : 0)));
|
|
46971
|
+
this.orgsLoading.set(false);
|
|
46972
|
+
resolve();
|
|
46973
|
+
},
|
|
46974
|
+
error: err => {
|
|
46975
|
+
this.orgsError.set(err);
|
|
46976
|
+
this.orgsLoading.set(false);
|
|
46977
|
+
resolve();
|
|
46978
|
+
},
|
|
46979
|
+
});
|
|
46980
|
+
});
|
|
46981
|
+
}
|
|
46982
|
+
tt(key) {
|
|
46983
|
+
return this.i18n.t(key, this.ns);
|
|
46984
|
+
}
|
|
46985
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccountViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46986
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AccountViewComponent, isStandalone: true, selector: "val-account-view", inputs: { config: "config" }, ngImport: i0, template: `
|
|
46987
|
+
<div class="page">
|
|
46988
|
+
<header class="page-header">
|
|
46989
|
+
<val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
|
|
46990
|
+
<val-title
|
|
46991
|
+
[props]="{
|
|
46992
|
+
size: 'large',
|
|
46993
|
+
color: 'dark',
|
|
46994
|
+
bold: false,
|
|
46995
|
+
content: pageDescription(),
|
|
46996
|
+
}"
|
|
46997
|
+
/>
|
|
46998
|
+
</header>
|
|
46999
|
+
|
|
47000
|
+
@if (resolvedConfig().showPendingInvites && pendingInvites().length > 0) {
|
|
47001
|
+
<val-title
|
|
47002
|
+
[props]="{
|
|
47003
|
+
size: 'medium',
|
|
47004
|
+
color: 'dark',
|
|
47005
|
+
bold: true,
|
|
47006
|
+
content: tt('pendingInvitesTitle'),
|
|
47007
|
+
}"
|
|
47008
|
+
/>
|
|
47009
|
+
@for (invite of pendingInvites(); track invite.orgId) {
|
|
47010
|
+
<val-invitation-card
|
|
47011
|
+
[props]="{
|
|
47012
|
+
token: invite.orgId,
|
|
47013
|
+
orgName: invite.orgName,
|
|
47014
|
+
inviterName: invite.inviterName,
|
|
47015
|
+
role: invite.roleId,
|
|
47016
|
+
accepting: inviteAccepting() === invite.orgId,
|
|
47017
|
+
disabled: !!inviteAccepting(),
|
|
47018
|
+
acceptLabel: tt('accept'),
|
|
47019
|
+
declineLabel: tt('decline'),
|
|
47020
|
+
}"
|
|
47021
|
+
(onAccept)="acceptPendingInvite(invite)"
|
|
47022
|
+
(onDecline)="declinePendingInvite(invite)"
|
|
47023
|
+
/>
|
|
47024
|
+
}
|
|
47025
|
+
}
|
|
47026
|
+
|
|
47027
|
+
@if (resolvedConfig().showOrganizations) {
|
|
47028
|
+
<!-- Organizations -->
|
|
47029
|
+
<section class="settings-section">
|
|
47030
|
+
<div class="section-header-row">
|
|
47031
|
+
<val-title
|
|
47032
|
+
[props]="{
|
|
47033
|
+
size: 'medium',
|
|
47034
|
+
color: 'dark',
|
|
47035
|
+
bold: true,
|
|
47036
|
+
content: orgsTitle(),
|
|
47037
|
+
}"
|
|
47038
|
+
/>
|
|
47039
|
+
@if (orgs().length > 1) {
|
|
47040
|
+
<ion-button fill="outline" color="dark" shape="round" size="small" (click)="onSwitchAccount()">
|
|
47041
|
+
{{ tt('orgsViewAll') }}
|
|
47042
|
+
</ion-button>
|
|
47043
|
+
}
|
|
47044
|
+
</div>
|
|
47045
|
+
<div class="section-body">
|
|
47046
|
+
@if (orgsLoading()) {
|
|
47047
|
+
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
47048
|
+
} @else if (orgsErrorState()) {
|
|
47049
|
+
<val-empty-state [props]="orgsErrorState()!" />
|
|
47050
|
+
} @else {
|
|
47051
|
+
@if (activeOrg(); as org) {
|
|
47052
|
+
<div class="orgs-list">
|
|
47053
|
+
<div class="org-card org-card--active">
|
|
47054
|
+
<div class="org-card__icon">
|
|
47055
|
+
<ion-icon name="business-outline" />
|
|
47056
|
+
</div>
|
|
47057
|
+
<div class="org-card__body">
|
|
47058
|
+
<span class="org-card__name">{{ org.name }}</span>
|
|
47059
|
+
<div class="org-card__meta">
|
|
47060
|
+
<span class="org-card__meta-item">
|
|
47061
|
+
<span class="org-card__meta-label">{{ tt('orgsLabelType') }}</span>
|
|
47062
|
+
{{ orgTypeLabel(org.type) }}
|
|
47063
|
+
</span>
|
|
47064
|
+
@if (activeOrgRole()) {
|
|
47065
|
+
<span class="org-card__meta-item">
|
|
47066
|
+
<span class="org-card__meta-label">{{ tt('orgsLabelRole') }}</span>
|
|
47067
|
+
{{ activeOrgRole() | titlecase }}
|
|
47068
|
+
</span>
|
|
47069
|
+
}
|
|
47070
|
+
<span class="org-card__meta-item">
|
|
47071
|
+
<span class="org-card__meta-label">{{ tt('orgsLabelStatus') }}</span>
|
|
47072
|
+
{{ tt('orgsStatusActive') }}
|
|
47073
|
+
</span>
|
|
47074
|
+
</div>
|
|
47075
|
+
</div>
|
|
47076
|
+
<div class="org-card__end">
|
|
47077
|
+
<ion-button fill="outline" color="dark" shape="round" size="small" (click)="onManageOrg()">
|
|
47078
|
+
{{ tt('orgsManage') }}
|
|
47079
|
+
</ion-button>
|
|
47080
|
+
</div>
|
|
47081
|
+
</div>
|
|
47082
|
+
</div>
|
|
47083
|
+
} @else if (orgs().length === 0) {
|
|
47084
|
+
<div class="orgs-empty-card">
|
|
47085
|
+
<div class="orgs-empty-card__main">
|
|
47086
|
+
<ion-icon name="people-outline" class="orgs-empty-card__icon" />
|
|
47087
|
+
<span class="orgs-empty-card__text">{{ orgsEmpty() }}</span>
|
|
47088
|
+
</div>
|
|
47089
|
+
<button class="orgs-empty-card__link" (click)="onMoreInfo()">
|
|
47090
|
+
{{ orgsMoreInfo() }}
|
|
47091
|
+
</button>
|
|
47092
|
+
</div>
|
|
47093
|
+
}
|
|
47094
|
+
@if (resolvedConfig().showNewOrgCta) {
|
|
47095
|
+
<!-- Nueva organizacion: CTA card con titulo, subtitulo y boton -->
|
|
47096
|
+
<val-cta-card class="org-new-cta-card" [props]="newOrgCtaProps()" (onAction)="onNewOrg()" />
|
|
47097
|
+
}
|
|
47098
|
+
}
|
|
47099
|
+
</div>
|
|
47100
|
+
</section>
|
|
47101
|
+
}
|
|
47102
|
+
|
|
47103
|
+
@if (resolvedConfig().showLogout) {
|
|
47104
|
+
<!-- Logout this session -->
|
|
47105
|
+
<section class="settings-section">
|
|
47106
|
+
<val-title
|
|
47107
|
+
[props]="{
|
|
47108
|
+
size: 'medium',
|
|
47109
|
+
color: 'dark',
|
|
47110
|
+
bold: true,
|
|
47111
|
+
content: logoutTitle(),
|
|
47112
|
+
}"
|
|
47113
|
+
/>
|
|
47114
|
+
<div class="section-body">
|
|
47115
|
+
<val-text
|
|
47116
|
+
[props]="{
|
|
47117
|
+
content: logoutHint(),
|
|
47118
|
+
size: 'medium',
|
|
47119
|
+
color: 'dark',
|
|
47120
|
+
bold: false,
|
|
47121
|
+
}"
|
|
47122
|
+
/>
|
|
47123
|
+
<div class="row-actions">
|
|
47124
|
+
<val-button [props]="logoutButtonProps()" (click)="onLogout()" />
|
|
47125
|
+
</div>
|
|
47126
|
+
</div>
|
|
47127
|
+
</section>
|
|
47128
|
+
}
|
|
47129
|
+
|
|
47130
|
+
@if (resolvedConfig().showDeleteAccount) {
|
|
47131
|
+
<!-- Delete account -->
|
|
47132
|
+
<section class="settings-section">
|
|
47133
|
+
<val-title
|
|
47134
|
+
[props]="{
|
|
47135
|
+
size: 'medium',
|
|
47136
|
+
color: 'dark',
|
|
47137
|
+
bold: true,
|
|
47138
|
+
content: dangerDeleteTitle(),
|
|
47139
|
+
}"
|
|
47140
|
+
/>
|
|
47141
|
+
<div class="section-body">
|
|
47142
|
+
<val-text
|
|
47143
|
+
[props]="{
|
|
47144
|
+
content: dangerDeleteHint(),
|
|
47145
|
+
size: 'medium',
|
|
47146
|
+
color: 'dark',
|
|
47147
|
+
bold: false,
|
|
47148
|
+
}"
|
|
47149
|
+
/>
|
|
47150
|
+
<div class="row-actions">
|
|
47151
|
+
<val-button [props]="deleteAccountButtonProps()" (onClick)="onDeleteAccount()" />
|
|
47152
|
+
</div>
|
|
47153
|
+
</div>
|
|
47154
|
+
</section>
|
|
47155
|
+
}
|
|
47156
|
+
</div>
|
|
47157
|
+
`, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.settings-section val-title{display:block;margin-bottom:12px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;flex-wrap:wrap;gap:8px}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.org-new-cta-card{display:block;margin-top:12px}.orgs-empty-card{background:var(--ion-color-secondary-tint, rgba(var(--ion-color-secondary-rgb, 130, 101, 208), .2));border-radius:18px;padding:18px 16px 12px;display:flex;flex-direction:column;gap:8px}.orgs-empty-card__main{display:flex;align-items:center;gap:10px}.orgs-empty-card__icon{font-size:20px;flex-shrink:0;color:var(--ion-color-dark)}.orgs-empty-card__text{font-size:.875rem;color:var(--ion-color-dark)}.orgs-empty-card__link{background:none;border:none;padding:0;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);text-align:left;text-decoration:underline;text-underline-offset:2px;font-family:inherit}.orgs-list{display:flex;flex-direction:column;gap:8px}.org-card{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:12px;background:var(--ion-color-light, #f4f5f8);border:1.5px solid transparent;cursor:pointer;transition:background .15s,border-color .15s}.org-card:active{opacity:.75}.org-card--active{border-color:var(--ion-color-primary);background:color-mix(in srgb,var(--ion-color-primary) 8%,transparent)}:host-context(body.dark) .org-card,:host-context(html.ion-palette-dark) .org-card,:host-context([data-theme=\"dark\"]) .org-card{background:#ffffff0d}:host-context(body.dark) .org-card--active,:host-context(html.ion-palette-dark) .org-card--active,:host-context([data-theme=\"dark\"]) .org-card--active{background:color-mix(in srgb,var(--ion-color-primary) 15%,transparent)}.org-card__icon{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;flex-shrink:0;font-size:20px;color:var(--ion-color-primary)}.org-card__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.org-card__name{font-weight:600;font-size:.95rem;color:var(--ion-color-dark);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.org-card__meta{display:flex;flex-direction:column;gap:1px;margin-top:3px}.org-card__meta-item{font-size:.78rem;color:var(--ion-color-dark)}.org-card__meta-label{font-weight:600;color:var(--ion-color-dark);margin-right:4px}.org-card__end{display:flex;align-items:center;gap:8px;flex-shrink:0}\n"], dependencies: [{ kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: CtaCardComponent, selector: "val-cta-card", inputs: ["props"], outputs: ["onAction"] }, { kind: "component", type: InvitationCardComponent, selector: "val-invitation-card", inputs: ["props"], outputs: ["onAccept", "onDecline"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { 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: "pipe", type: TitleCasePipe, name: "titlecase" }] }); }
|
|
47158
|
+
}
|
|
47159
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AccountViewComponent, decorators: [{
|
|
47160
|
+
type: Component,
|
|
47161
|
+
args: [{ selector: 'val-account-view', standalone: true, imports: [
|
|
47162
|
+
DisplayComponent,
|
|
47163
|
+
EmptyStateComponent,
|
|
47164
|
+
SkeletonLayoutComponent,
|
|
47165
|
+
TitleComponent,
|
|
47166
|
+
TextComponent,
|
|
47167
|
+
ButtonComponent,
|
|
47168
|
+
CtaCardComponent,
|
|
47169
|
+
InvitationCardComponent,
|
|
47170
|
+
IonIcon,
|
|
47171
|
+
IonButton,
|
|
47172
|
+
TitleCasePipe,
|
|
47173
|
+
], template: `
|
|
47174
|
+
<div class="page">
|
|
47175
|
+
<header class="page-header">
|
|
47176
|
+
<val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
|
|
47177
|
+
<val-title
|
|
47178
|
+
[props]="{
|
|
47179
|
+
size: 'large',
|
|
47180
|
+
color: 'dark',
|
|
47181
|
+
bold: false,
|
|
47182
|
+
content: pageDescription(),
|
|
47183
|
+
}"
|
|
47184
|
+
/>
|
|
47185
|
+
</header>
|
|
47186
|
+
|
|
47187
|
+
@if (resolvedConfig().showPendingInvites && pendingInvites().length > 0) {
|
|
47188
|
+
<val-title
|
|
47189
|
+
[props]="{
|
|
47190
|
+
size: 'medium',
|
|
47191
|
+
color: 'dark',
|
|
47192
|
+
bold: true,
|
|
47193
|
+
content: tt('pendingInvitesTitle'),
|
|
47194
|
+
}"
|
|
47195
|
+
/>
|
|
47196
|
+
@for (invite of pendingInvites(); track invite.orgId) {
|
|
47197
|
+
<val-invitation-card
|
|
47198
|
+
[props]="{
|
|
47199
|
+
token: invite.orgId,
|
|
47200
|
+
orgName: invite.orgName,
|
|
47201
|
+
inviterName: invite.inviterName,
|
|
47202
|
+
role: invite.roleId,
|
|
47203
|
+
accepting: inviteAccepting() === invite.orgId,
|
|
47204
|
+
disabled: !!inviteAccepting(),
|
|
47205
|
+
acceptLabel: tt('accept'),
|
|
47206
|
+
declineLabel: tt('decline'),
|
|
47207
|
+
}"
|
|
47208
|
+
(onAccept)="acceptPendingInvite(invite)"
|
|
47209
|
+
(onDecline)="declinePendingInvite(invite)"
|
|
47210
|
+
/>
|
|
47211
|
+
}
|
|
47212
|
+
}
|
|
47213
|
+
|
|
47214
|
+
@if (resolvedConfig().showOrganizations) {
|
|
47215
|
+
<!-- Organizations -->
|
|
47216
|
+
<section class="settings-section">
|
|
47217
|
+
<div class="section-header-row">
|
|
47218
|
+
<val-title
|
|
47219
|
+
[props]="{
|
|
47220
|
+
size: 'medium',
|
|
47221
|
+
color: 'dark',
|
|
47222
|
+
bold: true,
|
|
47223
|
+
content: orgsTitle(),
|
|
47224
|
+
}"
|
|
47225
|
+
/>
|
|
47226
|
+
@if (orgs().length > 1) {
|
|
47227
|
+
<ion-button fill="outline" color="dark" shape="round" size="small" (click)="onSwitchAccount()">
|
|
47228
|
+
{{ tt('orgsViewAll') }}
|
|
47229
|
+
</ion-button>
|
|
47230
|
+
}
|
|
47231
|
+
</div>
|
|
47232
|
+
<div class="section-body">
|
|
47233
|
+
@if (orgsLoading()) {
|
|
47234
|
+
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
47235
|
+
} @else if (orgsErrorState()) {
|
|
47236
|
+
<val-empty-state [props]="orgsErrorState()!" />
|
|
47237
|
+
} @else {
|
|
47238
|
+
@if (activeOrg(); as org) {
|
|
47239
|
+
<div class="orgs-list">
|
|
47240
|
+
<div class="org-card org-card--active">
|
|
47241
|
+
<div class="org-card__icon">
|
|
47242
|
+
<ion-icon name="business-outline" />
|
|
47243
|
+
</div>
|
|
47244
|
+
<div class="org-card__body">
|
|
47245
|
+
<span class="org-card__name">{{ org.name }}</span>
|
|
47246
|
+
<div class="org-card__meta">
|
|
47247
|
+
<span class="org-card__meta-item">
|
|
47248
|
+
<span class="org-card__meta-label">{{ tt('orgsLabelType') }}</span>
|
|
47249
|
+
{{ orgTypeLabel(org.type) }}
|
|
47250
|
+
</span>
|
|
47251
|
+
@if (activeOrgRole()) {
|
|
47252
|
+
<span class="org-card__meta-item">
|
|
47253
|
+
<span class="org-card__meta-label">{{ tt('orgsLabelRole') }}</span>
|
|
47254
|
+
{{ activeOrgRole() | titlecase }}
|
|
47255
|
+
</span>
|
|
47256
|
+
}
|
|
47257
|
+
<span class="org-card__meta-item">
|
|
47258
|
+
<span class="org-card__meta-label">{{ tt('orgsLabelStatus') }}</span>
|
|
47259
|
+
{{ tt('orgsStatusActive') }}
|
|
47260
|
+
</span>
|
|
47261
|
+
</div>
|
|
47262
|
+
</div>
|
|
47263
|
+
<div class="org-card__end">
|
|
47264
|
+
<ion-button fill="outline" color="dark" shape="round" size="small" (click)="onManageOrg()">
|
|
47265
|
+
{{ tt('orgsManage') }}
|
|
47266
|
+
</ion-button>
|
|
47267
|
+
</div>
|
|
47268
|
+
</div>
|
|
47269
|
+
</div>
|
|
47270
|
+
} @else if (orgs().length === 0) {
|
|
47271
|
+
<div class="orgs-empty-card">
|
|
47272
|
+
<div class="orgs-empty-card__main">
|
|
47273
|
+
<ion-icon name="people-outline" class="orgs-empty-card__icon" />
|
|
47274
|
+
<span class="orgs-empty-card__text">{{ orgsEmpty() }}</span>
|
|
47275
|
+
</div>
|
|
47276
|
+
<button class="orgs-empty-card__link" (click)="onMoreInfo()">
|
|
47277
|
+
{{ orgsMoreInfo() }}
|
|
47278
|
+
</button>
|
|
47279
|
+
</div>
|
|
47280
|
+
}
|
|
47281
|
+
@if (resolvedConfig().showNewOrgCta) {
|
|
47282
|
+
<!-- Nueva organizacion: CTA card con titulo, subtitulo y boton -->
|
|
47283
|
+
<val-cta-card class="org-new-cta-card" [props]="newOrgCtaProps()" (onAction)="onNewOrg()" />
|
|
47284
|
+
}
|
|
47285
|
+
}
|
|
47286
|
+
</div>
|
|
47287
|
+
</section>
|
|
47288
|
+
}
|
|
47289
|
+
|
|
47290
|
+
@if (resolvedConfig().showLogout) {
|
|
47291
|
+
<!-- Logout this session -->
|
|
47292
|
+
<section class="settings-section">
|
|
47293
|
+
<val-title
|
|
47294
|
+
[props]="{
|
|
47295
|
+
size: 'medium',
|
|
47296
|
+
color: 'dark',
|
|
47297
|
+
bold: true,
|
|
47298
|
+
content: logoutTitle(),
|
|
47299
|
+
}"
|
|
47300
|
+
/>
|
|
47301
|
+
<div class="section-body">
|
|
47302
|
+
<val-text
|
|
47303
|
+
[props]="{
|
|
47304
|
+
content: logoutHint(),
|
|
47305
|
+
size: 'medium',
|
|
47306
|
+
color: 'dark',
|
|
47307
|
+
bold: false,
|
|
47308
|
+
}"
|
|
47309
|
+
/>
|
|
47310
|
+
<div class="row-actions">
|
|
47311
|
+
<val-button [props]="logoutButtonProps()" (click)="onLogout()" />
|
|
47312
|
+
</div>
|
|
47313
|
+
</div>
|
|
47314
|
+
</section>
|
|
47315
|
+
}
|
|
47316
|
+
|
|
47317
|
+
@if (resolvedConfig().showDeleteAccount) {
|
|
47318
|
+
<!-- Delete account -->
|
|
47319
|
+
<section class="settings-section">
|
|
47320
|
+
<val-title
|
|
47321
|
+
[props]="{
|
|
47322
|
+
size: 'medium',
|
|
47323
|
+
color: 'dark',
|
|
47324
|
+
bold: true,
|
|
47325
|
+
content: dangerDeleteTitle(),
|
|
47326
|
+
}"
|
|
47327
|
+
/>
|
|
47328
|
+
<div class="section-body">
|
|
47329
|
+
<val-text
|
|
47330
|
+
[props]="{
|
|
47331
|
+
content: dangerDeleteHint(),
|
|
47332
|
+
size: 'medium',
|
|
47333
|
+
color: 'dark',
|
|
47334
|
+
bold: false,
|
|
47335
|
+
}"
|
|
47336
|
+
/>
|
|
47337
|
+
<div class="row-actions">
|
|
47338
|
+
<val-button [props]="deleteAccountButtonProps()" (onClick)="onDeleteAccount()" />
|
|
47339
|
+
</div>
|
|
47340
|
+
</div>
|
|
47341
|
+
</section>
|
|
47342
|
+
}
|
|
47343
|
+
</div>
|
|
47344
|
+
`, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.settings-section{padding:16px 0}.settings-section+.settings-section{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.settings-section val-title{display:block;margin-bottom:12px}.section-body{display:flex;flex-direction:column;gap:10px}.row-actions{margin-top:12px}.row-actions--gap{display:flex;flex-wrap:wrap;gap:8px}.section-header-row{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:8px}.org-new-cta-card{display:block;margin-top:12px}.orgs-empty-card{background:var(--ion-color-secondary-tint, rgba(var(--ion-color-secondary-rgb, 130, 101, 208), .2));border-radius:18px;padding:18px 16px 12px;display:flex;flex-direction:column;gap:8px}.orgs-empty-card__main{display:flex;align-items:center;gap:10px}.orgs-empty-card__icon{font-size:20px;flex-shrink:0;color:var(--ion-color-dark)}.orgs-empty-card__text{font-size:.875rem;color:var(--ion-color-dark)}.orgs-empty-card__link{background:none;border:none;padding:0;cursor:pointer;font-size:.8125rem;color:var(--ion-color-primary);text-align:left;text-decoration:underline;text-underline-offset:2px;font-family:inherit}.orgs-list{display:flex;flex-direction:column;gap:8px}.org-card{display:flex;align-items:center;gap:14px;padding:14px 16px;border-radius:12px;background:var(--ion-color-light, #f4f5f8);border:1.5px solid transparent;cursor:pointer;transition:background .15s,border-color .15s}.org-card:active{opacity:.75}.org-card--active{border-color:var(--ion-color-primary);background:color-mix(in srgb,var(--ion-color-primary) 8%,transparent)}:host-context(body.dark) .org-card,:host-context(html.ion-palette-dark) .org-card,:host-context([data-theme=\"dark\"]) .org-card{background:#ffffff0d}:host-context(body.dark) .org-card--active,:host-context(html.ion-palette-dark) .org-card--active,:host-context([data-theme=\"dark\"]) .org-card--active{background:color-mix(in srgb,var(--ion-color-primary) 15%,transparent)}.org-card__icon{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;flex-shrink:0;font-size:20px;color:var(--ion-color-primary)}.org-card__body{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.org-card__name{font-weight:600;font-size:.95rem;color:var(--ion-color-dark);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.org-card__meta{display:flex;flex-direction:column;gap:1px;margin-top:3px}.org-card__meta-item{font-size:.78rem;color:var(--ion-color-dark)}.org-card__meta-label{font-weight:600;color:var(--ion-color-dark);margin-right:4px}.org-card__end{display:flex;align-items:center;gap:8px;flex-shrink:0}\n"] }]
|
|
47345
|
+
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
47346
|
+
type: Input
|
|
47347
|
+
}] } });
|
|
47348
|
+
|
|
47349
|
+
/**
|
|
47350
|
+
* Helper para montar la vista Cuenta (`val-account-view`) como ruta en una app
|
|
47351
|
+
* del factory. El `config` se pasa por route `data` (`accountConfig`) y el
|
|
47352
|
+
* componente lo lee como fallback de su `@Input() config`.
|
|
47353
|
+
*
|
|
47354
|
+
* @example
|
|
47355
|
+
* ```ts
|
|
47356
|
+
* // settings.routes.ts
|
|
47357
|
+
* export const settingsRoutes: Routes = [
|
|
47358
|
+
* ...provideValtechAccountRoutes(),
|
|
47359
|
+
* { path: 'preferences', loadComponent: () => ... },
|
|
47360
|
+
* ];
|
|
47361
|
+
*
|
|
47362
|
+
* // con config acotada:
|
|
47363
|
+
* ...provideValtechAccountRoutes({ config: { showDeleteAccount: false } }),
|
|
47364
|
+
* ...provideValtechAccountRoutes({ config: { manageOrgRoute: '/app/org' } }),
|
|
47365
|
+
* ```
|
|
47366
|
+
*/
|
|
47367
|
+
function provideValtechAccountRoutes(opts) {
|
|
47368
|
+
return [
|
|
47369
|
+
{
|
|
47370
|
+
path: opts?.path ?? 'account',
|
|
47371
|
+
component: AccountViewComponent,
|
|
47372
|
+
data: { accountConfig: opts?.config },
|
|
47373
|
+
},
|
|
47374
|
+
];
|
|
47375
|
+
}
|
|
47376
|
+
|
|
47377
|
+
/** Built-in label sets for the three platform locales. */
|
|
47378
|
+
const CALLOUT_LABELS = {
|
|
47379
|
+
es: {
|
|
47380
|
+
NOTE: 'Nota',
|
|
47381
|
+
TIP: 'Tip',
|
|
47382
|
+
INFO: 'Info',
|
|
47383
|
+
IMPORTANT: 'Importante',
|
|
47384
|
+
WARNING: 'Atención',
|
|
47385
|
+
CAUTION: 'Precaución',
|
|
47386
|
+
},
|
|
47387
|
+
en: {
|
|
47388
|
+
NOTE: 'Note',
|
|
47389
|
+
TIP: 'Tip',
|
|
47390
|
+
INFO: 'Info',
|
|
47391
|
+
IMPORTANT: 'Important',
|
|
47392
|
+
WARNING: 'Warning',
|
|
47393
|
+
CAUTION: 'Caution',
|
|
47394
|
+
},
|
|
47395
|
+
pt: {
|
|
47396
|
+
NOTE: 'Nota',
|
|
47397
|
+
TIP: 'Dica',
|
|
47398
|
+
INFO: 'Info',
|
|
47399
|
+
IMPORTANT: 'Importante',
|
|
47400
|
+
WARNING: 'Atenção',
|
|
47401
|
+
CAUTION: 'Cuidado',
|
|
47402
|
+
},
|
|
47403
|
+
};
|
|
47404
|
+
/**
|
|
47405
|
+
* Per-callout-kind color (Ionic semantic color). Fixed across locales since
|
|
47406
|
+
* red = danger no matter what language you speak.
|
|
47407
|
+
*/
|
|
47408
|
+
const CALLOUT_COLORS = {
|
|
47409
|
+
NOTE: 'primary',
|
|
47410
|
+
TIP: 'success',
|
|
47411
|
+
INFO: 'tertiary',
|
|
47412
|
+
IMPORTANT: 'warning',
|
|
47413
|
+
WARNING: 'warning',
|
|
47414
|
+
CAUTION: 'danger',
|
|
47415
|
+
};
|
|
47416
|
+
const BOX_DRAWING = /[┌┐└┘├┤┬┴┼─│╔╗╚╝═║]/;
|
|
47417
|
+
const CALLOUT_RE = /^>\s*\[!(NOTE|TIP|INFO|WARNING|CAUTION|IMPORTANT)\]\s*(.*)$/i;
|
|
47418
|
+
const FENCE_RE = /^```([\w-]*)\s*$/;
|
|
47419
|
+
const HEADING_RE = /^(#{1,6})\s+(.+)$/;
|
|
47420
|
+
const SEPARATOR_RE = /^\s*(?:-{3,}|\*{3,}|_{3,})\s*$/;
|
|
47421
|
+
const UNORDERED_RE = /^\s*[-*+]\s+(.+)$/;
|
|
47422
|
+
const CHECKLIST_RE = /^\s*[-*+]\s+\[([ xX])\]\s+(.+)$/;
|
|
47423
|
+
const ORDERED_RE = /^\s*\d+\.\s+(.+)$/;
|
|
47424
|
+
const TABLE_DIVIDER_RE = /^\s*\|?[\s:|-]+\|?\s*$/;
|
|
47425
|
+
const TABLE_ROW_RE = /^\s*\|(.+)\|\s*$/;
|
|
47426
|
+
/**
|
|
47427
|
+
* Pure Markdown → ArticleMetadata parser. No Angular deps — usable from Node scripts
|
|
47428
|
+
* (build-time generation) and from the Angular `MarkdownArticleParserService` wrapper.
|
|
47429
|
+
*
|
|
47430
|
+
* Supported syntax:
|
|
47431
|
+
* - Headings (#, ##, ### …) → title / subtitle
|
|
47432
|
+
* - Paragraphs → paragraph (with `processLinks` + `allowPartialBold`)
|
|
47433
|
+
* - Lists (-, *, 1.) → unordered / ordered list (- [ ] / - [x] for checklist)
|
|
47434
|
+
* - Blockquotes (>) → quote, with GitHub callouts `> [!NOTE|TIP|INFO|WARNING|CAUTION|IMPORTANT]` mapped to notes
|
|
47435
|
+
* - Code fences (```lang) → code
|
|
47436
|
+
* - Box-drawing ASCII art (┌┐└┘│─) auto-wrapped as code
|
|
47437
|
+
* - Tables → flattened into paragraphs with bold keys
|
|
47438
|
+
* - Horizontal rules (---, ***, ___) → separator
|
|
47439
|
+
*/
|
|
47440
|
+
function parseMarkdownArticle(markdown, options) {
|
|
47441
|
+
const lines = normalize(markdown).split('\n');
|
|
47442
|
+
const elements = [];
|
|
47443
|
+
const labels = options?.calloutLabels ??
|
|
47444
|
+
(options?.locale ? CALLOUT_LABELS[options.locale] : CALLOUT_LABELS.es);
|
|
47445
|
+
let i = 0;
|
|
47446
|
+
while (i < lines.length) {
|
|
47447
|
+
const line = lines[i];
|
|
47448
|
+
if (line.trim() === '') {
|
|
47449
|
+
i++;
|
|
47450
|
+
continue;
|
|
47451
|
+
}
|
|
47452
|
+
const fence = line.match(FENCE_RE);
|
|
47453
|
+
if (fence) {
|
|
47454
|
+
const lang = fence[1] || undefined;
|
|
47455
|
+
const body = [];
|
|
47456
|
+
i++;
|
|
47457
|
+
while (i < lines.length && !FENCE_RE.test(lines[i])) {
|
|
47458
|
+
body.push(lines[i]);
|
|
47459
|
+
i++;
|
|
47460
|
+
}
|
|
47461
|
+
i++;
|
|
47462
|
+
elements.push({
|
|
47463
|
+
type: 'code',
|
|
47464
|
+
props: { code: body.join('\n'), language: lang, theme: 'dark' },
|
|
47465
|
+
});
|
|
47466
|
+
continue;
|
|
47467
|
+
}
|
|
47468
|
+
if (BOX_DRAWING.test(line)) {
|
|
47469
|
+
const body = [];
|
|
47470
|
+
while (i < lines.length && (lines[i].trim() === '' || BOX_DRAWING.test(lines[i]))) {
|
|
47471
|
+
body.push(lines[i]);
|
|
47472
|
+
i++;
|
|
47473
|
+
}
|
|
47474
|
+
while (body.length && body[body.length - 1].trim() === '')
|
|
47475
|
+
body.pop();
|
|
47476
|
+
elements.push({
|
|
47477
|
+
type: 'code',
|
|
47478
|
+
props: { code: body.join('\n'), language: 'text', theme: 'dark' },
|
|
47479
|
+
});
|
|
47480
|
+
continue;
|
|
47481
|
+
}
|
|
47482
|
+
if (SEPARATOR_RE.test(line)) {
|
|
47483
|
+
elements.push({ type: 'separator', props: { style: 'line' } });
|
|
47484
|
+
i++;
|
|
47485
|
+
continue;
|
|
47486
|
+
}
|
|
47487
|
+
const heading = line.match(HEADING_RE);
|
|
47488
|
+
if (heading) {
|
|
47489
|
+
elements.push(makeHeading(heading[1].length, heading[2].trim()));
|
|
47490
|
+
i++;
|
|
47491
|
+
continue;
|
|
47492
|
+
}
|
|
47493
|
+
if (line.startsWith('>')) {
|
|
47494
|
+
const block = [];
|
|
47495
|
+
while (i < lines.length && lines[i].startsWith('>')) {
|
|
47496
|
+
block.push(lines[i]);
|
|
47497
|
+
i++;
|
|
47498
|
+
}
|
|
47499
|
+
elements.push(makeQuoteOrCallout(block, labels));
|
|
47500
|
+
continue;
|
|
47501
|
+
}
|
|
47502
|
+
if (TABLE_ROW_RE.test(line)) {
|
|
47503
|
+
const rows = [];
|
|
47504
|
+
while (i < lines.length && TABLE_ROW_RE.test(lines[i])) {
|
|
47505
|
+
rows.push(lines[i]);
|
|
47506
|
+
i++;
|
|
47507
|
+
}
|
|
47508
|
+
elements.push(...makeTable(rows));
|
|
47509
|
+
continue;
|
|
47510
|
+
}
|
|
47511
|
+
if (CHECKLIST_RE.test(line) || UNORDERED_RE.test(line) || ORDERED_RE.test(line)) {
|
|
47512
|
+
const listType = CHECKLIST_RE.test(line)
|
|
47513
|
+
? 'checklist'
|
|
47514
|
+
: ORDERED_RE.test(line)
|
|
47515
|
+
? 'ordered'
|
|
47516
|
+
: 'unordered';
|
|
47517
|
+
const items = [];
|
|
47518
|
+
while (i < lines.length && lines[i].trim() !== '') {
|
|
47519
|
+
const cur = lines[i];
|
|
47520
|
+
const check = cur.match(CHECKLIST_RE);
|
|
47521
|
+
const unord = cur.match(UNORDERED_RE);
|
|
47522
|
+
const ord = cur.match(ORDERED_RE);
|
|
47523
|
+
if (check)
|
|
47524
|
+
items.push({ text: processInlineBold(check[2].trim()) });
|
|
47525
|
+
else if (ord && listType === 'ordered')
|
|
47526
|
+
items.push({ text: processInlineBold(ord[1].trim()) });
|
|
47527
|
+
else if (unord && listType !== 'ordered')
|
|
47528
|
+
items.push({ text: processInlineBold(unord[1].trim()) });
|
|
47529
|
+
else
|
|
47530
|
+
break;
|
|
47531
|
+
i++;
|
|
47532
|
+
}
|
|
47533
|
+
elements.push({ type: 'list', props: { items, listType } });
|
|
47534
|
+
continue;
|
|
47535
|
+
}
|
|
47536
|
+
const paragraph = [];
|
|
47537
|
+
while (i < lines.length && lines[i].trim() !== '' && !startsNewBlock(lines[i])) {
|
|
47538
|
+
paragraph.push(lines[i]);
|
|
47539
|
+
i++;
|
|
47540
|
+
}
|
|
47541
|
+
const text = processInlineBold(paragraph.join(' ').trim());
|
|
47542
|
+
if (text) {
|
|
47543
|
+
elements.push({
|
|
47544
|
+
type: 'paragraph',
|
|
47545
|
+
props: {
|
|
47546
|
+
content: text,
|
|
47547
|
+
size: 'medium',
|
|
47548
|
+
color: 'dark',
|
|
47549
|
+
bold: false,
|
|
47550
|
+
processLinks: true,
|
|
47551
|
+
allowPartialBold: true,
|
|
47552
|
+
},
|
|
47553
|
+
});
|
|
47554
|
+
}
|
|
47555
|
+
}
|
|
47556
|
+
// Strip parser-only options before merging into ArticleMetadata
|
|
47557
|
+
const { locale: _l, calloutLabels: _c, ...metadataOverrides } = options ?? {};
|
|
45464
47558
|
return {
|
|
45465
47559
|
elements,
|
|
45466
47560
|
maxWidth: '900px',
|
|
@@ -47316,102 +49410,6 @@ function beautifyLegalArticle(article) {
|
|
|
47316
49410
|
};
|
|
47317
49411
|
}
|
|
47318
49412
|
|
|
47319
|
-
class OrgService {
|
|
47320
|
-
constructor(config, http) {
|
|
47321
|
-
this.config = config;
|
|
47322
|
-
this.http = http;
|
|
47323
|
-
}
|
|
47324
|
-
get baseUrl() {
|
|
47325
|
-
return `${this.config.apiUrl}/org`;
|
|
47326
|
-
}
|
|
47327
|
-
listMyOrgs() {
|
|
47328
|
-
return this.http.get(`${this.baseUrl}/my`).pipe(map$1(r => r.organizations));
|
|
47329
|
-
}
|
|
47330
|
-
listMyOrgsPage(params) {
|
|
47331
|
-
const queryParams = new URLSearchParams();
|
|
47332
|
-
if (params?.limit)
|
|
47333
|
-
queryParams.set('limit', String(params.limit));
|
|
47334
|
-
if (params?.nextToken)
|
|
47335
|
-
queryParams.set('nextToken', params.nextToken);
|
|
47336
|
-
const qs = queryParams.toString();
|
|
47337
|
-
const url = `${this.baseUrl}/my${qs ? '?' + qs : ''}`;
|
|
47338
|
-
return this.http.get(url);
|
|
47339
|
-
}
|
|
47340
|
-
getOrg(orgId) {
|
|
47341
|
-
return this.http.get(`${this.baseUrl}/${orgId}`).pipe(map$1(r => r.organization));
|
|
47342
|
-
}
|
|
47343
|
-
createOrg(req) {
|
|
47344
|
-
return this.http.post(`${this.baseUrl}`, req).pipe(map$1(r => r.organization));
|
|
47345
|
-
}
|
|
47346
|
-
updateOrg(orgId, req) {
|
|
47347
|
-
return this.http
|
|
47348
|
-
.put(`${this.baseUrl}/${orgId}`, req)
|
|
47349
|
-
.pipe(map$1(r => r.organization));
|
|
47350
|
-
}
|
|
47351
|
-
deleteOrg(orgId) {
|
|
47352
|
-
return this.http.delete(`${this.baseUrl}/${orgId}`);
|
|
47353
|
-
}
|
|
47354
|
-
inviteUser(orgId, req) {
|
|
47355
|
-
return this.http.post(`${this.baseUrl}/${orgId}/invite`, req);
|
|
47356
|
-
}
|
|
47357
|
-
leaveOrg(orgId) {
|
|
47358
|
-
return this.http.post(`${this.baseUrl}/${orgId}/leave`, {});
|
|
47359
|
-
}
|
|
47360
|
-
getOrgMembers(orgId, params) {
|
|
47361
|
-
const queryParams = new URLSearchParams();
|
|
47362
|
-
if (params?.limit)
|
|
47363
|
-
queryParams.set('limit', String(params.limit));
|
|
47364
|
-
if (params?.nextToken)
|
|
47365
|
-
queryParams.set('nextToken', params.nextToken);
|
|
47366
|
-
const qs = queryParams.toString();
|
|
47367
|
-
const url = `${this.baseUrl}/${orgId}/members${qs ? '?' + qs : ''}`;
|
|
47368
|
-
return this.http.get(url);
|
|
47369
|
-
}
|
|
47370
|
-
listOrgRoles(orgId) {
|
|
47371
|
-
return this.http
|
|
47372
|
-
.get(`${this.baseUrl}/${orgId}/roles`)
|
|
47373
|
-
.pipe(map$1(r => r.roles ?? []));
|
|
47374
|
-
}
|
|
47375
|
-
changeMemberRole(orgId, userId, roleId) {
|
|
47376
|
-
const body = { roleId };
|
|
47377
|
-
return this.http.put(`${this.baseUrl}/${orgId}/members/${userId}/role`, body);
|
|
47378
|
-
}
|
|
47379
|
-
removeMember(orgId, userId) {
|
|
47380
|
-
return this.http.delete(`${this.baseUrl}/${orgId}/members/${userId}`);
|
|
47381
|
-
}
|
|
47382
|
-
transferOwnership(orgId, newOwnerId) {
|
|
47383
|
-
return this.http
|
|
47384
|
-
.post(`${this.baseUrl}/${orgId}/transfer-ownership`, { newOwnerId })
|
|
47385
|
-
.pipe(map$1(r => r.organization));
|
|
47386
|
-
}
|
|
47387
|
-
validateInviteToken(token) {
|
|
47388
|
-
return this.http.post(`${this.config.apiUrl}/v2/actions/validate`, { token });
|
|
47389
|
-
}
|
|
47390
|
-
executeInviteToken(token) {
|
|
47391
|
-
return this.http.post(`${this.config.apiUrl}/v2/actions/execute`, { token });
|
|
47392
|
-
}
|
|
47393
|
-
getPendingInvitations() {
|
|
47394
|
-
return this.http
|
|
47395
|
-
.get(`${this.config.apiUrl}/organizations/invitations/pending`)
|
|
47396
|
-
.pipe(map$1(r => r.items ?? []));
|
|
47397
|
-
}
|
|
47398
|
-
acceptInvitation(orgId) {
|
|
47399
|
-
return this.http.post(`${this.baseUrl}/invitations/${orgId}/accept`, {});
|
|
47400
|
-
}
|
|
47401
|
-
declineInvitation(orgId) {
|
|
47402
|
-
return this.http.post(`${this.baseUrl}/invitations/${orgId}/decline`, {});
|
|
47403
|
-
}
|
|
47404
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: i1$3.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
47405
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgService, providedIn: 'root' }); }
|
|
47406
|
-
}
|
|
47407
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgService, decorators: [{
|
|
47408
|
-
type: Injectable,
|
|
47409
|
-
args: [{ providedIn: 'root' }]
|
|
47410
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
47411
|
-
type: Inject,
|
|
47412
|
-
args: [VALTECH_AUTH_CONFIG]
|
|
47413
|
-
}] }, { type: i1$3.HttpClient }] });
|
|
47414
|
-
|
|
47415
49413
|
/**
|
|
47416
49414
|
* Preferences types — Fase 1 schema simple (theme + language + notifications.master).
|
|
47417
49415
|
* Doc canónico: /apps/{appId}/users/{uid}/preferences/main
|
|
@@ -55700,5 +57698,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
55700
57698
|
* Generated bundle index. Do not edit.
|
|
55701
57699
|
*/
|
|
55702
57700
|
|
|
55703
|
-
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, 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, 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, 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, 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, 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, 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 };
|
|
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 };
|
|
55704
57702
|
//# sourceMappingURL=valtech-components.mjs.map
|