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