valtech-components 2.0.997 → 2.0.998
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/organisms/api-keys-modal/api-keys-modal.component.mjs +385 -0
- package/esm2022/lib/components/organisms/api-keys-modal/api-keys-modal.i18n.mjs +63 -0
- package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.component.mjs +313 -0
- package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.i18n.mjs +63 -0
- package/esm2022/lib/components/organisms/organization-view/organization-view.component.mjs +76 -1
- package/esm2022/lib/components/organisms/organization-view/organization-view.i18n.mjs +5 -1
- package/esm2022/lib/services/apikeys/api-keys.service.mjs +46 -0
- package/esm2022/lib/services/apikeys/types.mjs +7 -0
- package/esm2022/lib/services/auth/auth.service.mjs +14 -1
- package/esm2022/lib/services/auth/types.mjs +1 -1
- package/esm2022/lib/services/org/org.service.mjs +8 -1
- package/esm2022/lib/services/org/types.mjs +1 -1
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +4 -1
- package/fesm2022/valtech-components.mjs +982 -42
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/api-keys-modal/api-keys-modal.component.d.ts +44 -0
- package/lib/components/organisms/api-keys-modal/api-keys-modal.i18n.d.ts +6 -0
- package/lib/components/organisms/member-import-modal/member-import-modal.component.d.ts +47 -0
- package/lib/components/organisms/member-import-modal/member-import-modal.i18n.d.ts +6 -0
- package/lib/components/organisms/organization-view/organization-view.component.d.ts +5 -0
- package/lib/services/apikeys/api-keys.service.d.ts +25 -0
- package/lib/services/apikeys/types.d.ts +46 -0
- package/lib/services/auth/auth.service.d.ts +7 -1
- package/lib/services/auth/types.d.ts +23 -0
- package/lib/services/org/org.service.d.ts +6 -1
- package/lib/services/org/types.d.ts +30 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +5 -1
|
@@ -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.998';
|
|
58
58
|
|
|
59
59
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
60
60
|
let isRefreshing = false;
|
|
@@ -8658,6 +8658,19 @@ class AuthService {
|
|
|
8658
8658
|
.post(`${this.baseUrl}/reset-password`, request)
|
|
8659
8659
|
.pipe(catchError(error => this.handleAuthError(error)));
|
|
8660
8660
|
}
|
|
8661
|
+
/**
|
|
8662
|
+
* Activa una cuenta pre-aprovisionada por una organización (ADR-023): define
|
|
8663
|
+
* la contraseña con el token del enlace de email. En éxito el backend devuelve
|
|
8664
|
+
* tokens de auto-signin → el usuario queda logueado (mismo flujo que verify-email).
|
|
8665
|
+
*/
|
|
8666
|
+
activateAccount(request) {
|
|
8667
|
+
this.stateService.clearError();
|
|
8668
|
+
return this.http.post(`${this.baseUrl}/activate`, request).pipe(tap(response => {
|
|
8669
|
+
if (response.activated && response.accessToken) {
|
|
8670
|
+
this.handleSuccessfulAuth(response);
|
|
8671
|
+
}
|
|
8672
|
+
}), catchError(error => this.handleAuthError(error)));
|
|
8673
|
+
}
|
|
8661
8674
|
/**
|
|
8662
8675
|
* Cambia la contraseña del usuario autenticado.
|
|
8663
8676
|
* Requiere la contraseña actual para verificación.
|
|
@@ -41737,7 +41750,7 @@ const PROFILE_VIEW_I18N = {
|
|
|
41737
41750
|
const HANDLE_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
41738
41751
|
const HANDLE_MIN = 3;
|
|
41739
41752
|
const HANDLE_MAX = 20;
|
|
41740
|
-
const DEFAULT_NAMESPACE$
|
|
41753
|
+
const DEFAULT_NAMESPACE$h = 'Settings.Profile';
|
|
41741
41754
|
/**
|
|
41742
41755
|
* `val-profile-view` — vista Perfil full-feature autocontenida (organism).
|
|
41743
41756
|
*
|
|
@@ -41787,7 +41800,7 @@ class ProfileViewComponent {
|
|
|
41787
41800
|
showPhone: merged.showPhone ?? true,
|
|
41788
41801
|
showShareCta: merged.showShareCta ?? true,
|
|
41789
41802
|
profileBaseUrl: merged.profileBaseUrl ?? '',
|
|
41790
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
41803
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$h,
|
|
41791
41804
|
onSaved: merged.onSaved,
|
|
41792
41805
|
onAvatarUploaded: merged.onAvatarUploaded,
|
|
41793
41806
|
};
|
|
@@ -42703,7 +42716,7 @@ const PREFERENCES_VIEW_I18N = {
|
|
|
42703
42716
|
},
|
|
42704
42717
|
};
|
|
42705
42718
|
|
|
42706
|
-
const DEFAULT_NAMESPACE$
|
|
42719
|
+
const DEFAULT_NAMESPACE$g = 'Settings.General';
|
|
42707
42720
|
const DEFAULT_LANGUAGES = ['es', 'en'];
|
|
42708
42721
|
/**
|
|
42709
42722
|
* `val-preferences-view` — vista de preferencias de UI cross-app (tema +
|
|
@@ -42740,7 +42753,7 @@ class PreferencesViewComponent {
|
|
|
42740
42753
|
showLanguage: merged.showLanguage ?? true,
|
|
42741
42754
|
showFontSize: merged.showFontSize ?? true,
|
|
42742
42755
|
supportedLanguages: merged.supportedLanguages ?? DEFAULT_LANGUAGES,
|
|
42743
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
42756
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$g,
|
|
42744
42757
|
onThemeChanged: merged.onThemeChanged,
|
|
42745
42758
|
onLanguageChanged: merged.onLanguageChanged,
|
|
42746
42759
|
onFontSizeChanged: merged.onFontSizeChanged,
|
|
@@ -44496,7 +44509,7 @@ const SECURITY_VIEW_I18N = {
|
|
|
44496
44509
|
};
|
|
44497
44510
|
|
|
44498
44511
|
addIcons({ laptopOutline, phonePortraitOutline });
|
|
44499
|
-
const DEFAULT_NAMESPACE$
|
|
44512
|
+
const DEFAULT_NAMESPACE$f = 'Settings.Security';
|
|
44500
44513
|
/**
|
|
44501
44514
|
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
44502
44515
|
*
|
|
@@ -44545,7 +44558,7 @@ class SecurityViewComponent {
|
|
|
44545
44558
|
showChangeEmail: merged.showChangeEmail ?? true,
|
|
44546
44559
|
showMfa: merged.showMfa ?? true,
|
|
44547
44560
|
showPolicies: merged.showPolicies ?? true,
|
|
44548
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
44561
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$f,
|
|
44549
44562
|
handleDeepLinks: merged.handleDeepLinks ?? true,
|
|
44550
44563
|
homeRoute: merged.homeRoute ?? '/app/home',
|
|
44551
44564
|
onMfaCompleted: merged.onMfaCompleted,
|
|
@@ -45347,6 +45360,13 @@ class OrgService {
|
|
|
45347
45360
|
inviteUser(orgId, req) {
|
|
45348
45361
|
return this.http.post(`${this.baseUrl}/${orgId}/invite`, req);
|
|
45349
45362
|
}
|
|
45363
|
+
/**
|
|
45364
|
+
* Crea/asigna miembros en masa (ADR-023). Resultado por-fila (partial success):
|
|
45365
|
+
* `created` (pre-aprovisionado), `assigned` (ya existía), `skipped`, `error`.
|
|
45366
|
+
*/
|
|
45367
|
+
importMembers(orgId, req) {
|
|
45368
|
+
return this.http.post(`${this.baseUrl}/${orgId}/members/import`, req);
|
|
45369
|
+
}
|
|
45350
45370
|
leaveOrg(orgId) {
|
|
45351
45371
|
return this.http.post(`${this.baseUrl}/${orgId}/leave`, {});
|
|
45352
45372
|
}
|
|
@@ -45451,7 +45471,7 @@ const CREATE_ORG_MODAL_I18N = {
|
|
|
45451
45471
|
},
|
|
45452
45472
|
};
|
|
45453
45473
|
|
|
45454
|
-
const DEFAULT_NAMESPACE$
|
|
45474
|
+
const DEFAULT_NAMESPACE$e = 'CreateOrgModal';
|
|
45455
45475
|
/**
|
|
45456
45476
|
* `val-create-org-modal` — modal de creación de organización (organism
|
|
45457
45477
|
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
@@ -45477,10 +45497,10 @@ class CreateOrgModalComponent {
|
|
|
45477
45497
|
this.toast = inject(ToastService);
|
|
45478
45498
|
this.errors = inject(ValtechErrorService);
|
|
45479
45499
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45480
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45500
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$e;
|
|
45481
45501
|
this._busy = signal(false);
|
|
45482
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45483
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45502
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$e)) {
|
|
45503
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$e, CREATE_ORG_MODAL_I18N);
|
|
45484
45504
|
}
|
|
45485
45505
|
this.formMeta = signal(this.buildFormMeta());
|
|
45486
45506
|
effect(() => {
|
|
@@ -45716,7 +45736,7 @@ const DELETE_ACCOUNT_MODAL_I18N = {
|
|
|
45716
45736
|
},
|
|
45717
45737
|
};
|
|
45718
45738
|
|
|
45719
|
-
const DEFAULT_NAMESPACE$
|
|
45739
|
+
const DEFAULT_NAMESPACE$d = 'Settings.DeleteAccount';
|
|
45720
45740
|
/**
|
|
45721
45741
|
* `val-delete-account-modal` — modal de eliminación de cuenta (organism,
|
|
45722
45742
|
* cuenta-específico). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -45742,7 +45762,7 @@ class DeleteAccountModalComponent {
|
|
|
45742
45762
|
this.i18n = inject(I18nService);
|
|
45743
45763
|
this.toast = inject(ToastService);
|
|
45744
45764
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45745
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45765
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$d;
|
|
45746
45766
|
this.hasPassword = signal(null);
|
|
45747
45767
|
this.codeSent = signal(false);
|
|
45748
45768
|
this.formState = signal(ComponentStates.ENABLED);
|
|
@@ -45809,8 +45829,8 @@ class DeleteAccountModalComponent {
|
|
|
45809
45829
|
],
|
|
45810
45830
|
actions: this.submitBtn('delete-code-submit', 'confirmCta'),
|
|
45811
45831
|
}));
|
|
45812
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45813
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45832
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$d)) {
|
|
45833
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$d, DELETE_ACCOUNT_MODAL_I18N);
|
|
45814
45834
|
}
|
|
45815
45835
|
}
|
|
45816
45836
|
ngOnInit() {
|
|
@@ -46011,7 +46031,7 @@ const ORG_INFO_SHEET_I18N = {
|
|
|
46011
46031
|
},
|
|
46012
46032
|
};
|
|
46013
46033
|
|
|
46014
|
-
const DEFAULT_NAMESPACE$
|
|
46034
|
+
const DEFAULT_NAMESPACE$c = 'OrgInfoSheet';
|
|
46015
46035
|
/**
|
|
46016
46036
|
* `val-org-info-sheet` — sheet informativo "¿Qué son las organizaciones?".
|
|
46017
46037
|
* Extraído del `OrgInfoSheetComponent` inline de `AccountPage` bajo el proceso de
|
|
@@ -46056,15 +46076,15 @@ class OrgInfoSheetComponent {
|
|
|
46056
46076
|
text: this.closeProps.text || this.resolvedCloseLabel(),
|
|
46057
46077
|
}));
|
|
46058
46078
|
addIcons({ peopleOutline, swapHorizontalOutline, mailOutline });
|
|
46059
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46060
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46079
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$c)) {
|
|
46080
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$c, ORG_INFO_SHEET_I18N);
|
|
46061
46081
|
}
|
|
46062
46082
|
}
|
|
46063
46083
|
dismiss() {
|
|
46064
46084
|
this._modalRef?.dismiss(null, 'cancel');
|
|
46065
46085
|
}
|
|
46066
46086
|
tt(key) {
|
|
46067
|
-
return this.i18n.t(key, DEFAULT_NAMESPACE$
|
|
46087
|
+
return this.i18n.t(key, DEFAULT_NAMESPACE$c);
|
|
46068
46088
|
}
|
|
46069
46089
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46070
46090
|
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: `
|
|
@@ -46231,7 +46251,7 @@ const SWITCH_ORG_MODAL_I18N = {
|
|
|
46231
46251
|
},
|
|
46232
46252
|
};
|
|
46233
46253
|
|
|
46234
|
-
const DEFAULT_NAMESPACE$
|
|
46254
|
+
const DEFAULT_NAMESPACE$b = 'Settings.SwitchOrg';
|
|
46235
46255
|
addIcons({ businessOutline, checkmarkCircleOutline });
|
|
46236
46256
|
/**
|
|
46237
46257
|
* `val-switch-org-modal` — modal de cambio de organización activa (organism
|
|
@@ -46257,7 +46277,7 @@ class SwitchOrgModalComponent {
|
|
|
46257
46277
|
this.orgSwitch = inject(OrgSwitchService);
|
|
46258
46278
|
this.errors = inject(ValtechErrorService);
|
|
46259
46279
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
46260
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
46280
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$b;
|
|
46261
46281
|
this.orgs = signal([]);
|
|
46262
46282
|
this.loading = signal(false);
|
|
46263
46283
|
this.query = signal('');
|
|
@@ -46273,8 +46293,8 @@ class SwitchOrgModalComponent {
|
|
|
46273
46293
|
return list;
|
|
46274
46294
|
return list.filter(o => o.name.toLowerCase().includes(q));
|
|
46275
46295
|
});
|
|
46276
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46277
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46296
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$b)) {
|
|
46297
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$b, SWITCH_ORG_MODAL_I18N);
|
|
46278
46298
|
}
|
|
46279
46299
|
this.loadOrgs();
|
|
46280
46300
|
}
|
|
@@ -46592,7 +46612,7 @@ const ACCOUNT_VIEW_I18N = {
|
|
|
46592
46612
|
};
|
|
46593
46613
|
|
|
46594
46614
|
addIcons({ peopleOutline, businessOutline, chevronForwardOutline, swapHorizontalOutline, mailOutline });
|
|
46595
|
-
const DEFAULT_NAMESPACE$
|
|
46615
|
+
const DEFAULT_NAMESPACE$a = 'Settings.Account';
|
|
46596
46616
|
const DEFAULT_MANAGE_ORG_ROUTE = '/app/settings/organization';
|
|
46597
46617
|
/**
|
|
46598
46618
|
* `val-account-view` — vista Cuenta full-feature autocontenida (organism).
|
|
@@ -46633,7 +46653,7 @@ class AccountViewComponent {
|
|
|
46633
46653
|
showNewOrgCta: merged.showNewOrgCta ?? true,
|
|
46634
46654
|
showLogout: merged.showLogout ?? true,
|
|
46635
46655
|
showDeleteAccount: merged.showDeleteAccount ?? true,
|
|
46636
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
46656
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$a,
|
|
46637
46657
|
manageOrgRoute: merged.manageOrgRoute ?? DEFAULT_MANAGE_ORG_ROUTE,
|
|
46638
46658
|
onOrgSwitched: merged.onOrgSwitched,
|
|
46639
46659
|
onOrgCreated: merged.onOrgCreated,
|
|
@@ -47358,7 +47378,7 @@ const EDIT_ORG_MODAL_I18N = {
|
|
|
47358
47378
|
},
|
|
47359
47379
|
};
|
|
47360
47380
|
|
|
47361
|
-
const DEFAULT_NAMESPACE$
|
|
47381
|
+
const DEFAULT_NAMESPACE$9 = 'EditOrgModal';
|
|
47362
47382
|
/**
|
|
47363
47383
|
* `val-edit-org-modal` — modal de edición de organización (nombre + descripción).
|
|
47364
47384
|
* Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por la vista de
|
|
@@ -47385,10 +47405,10 @@ class EditOrgModalComponent {
|
|
|
47385
47405
|
/** Organización a editar (pasada por `componentProps`). */
|
|
47386
47406
|
this.org = null;
|
|
47387
47407
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47388
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
47408
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$9;
|
|
47389
47409
|
this.saving = signal(false);
|
|
47390
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
47391
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
47410
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$9)) {
|
|
47411
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$9, EDIT_ORG_MODAL_I18N);
|
|
47392
47412
|
}
|
|
47393
47413
|
this.formMeta = signal(this.buildFormMeta());
|
|
47394
47414
|
effect(() => {
|
|
@@ -47626,7 +47646,7 @@ const INVITE_MEMBER_MODAL_I18N = {
|
|
|
47626
47646
|
},
|
|
47627
47647
|
};
|
|
47628
47648
|
|
|
47629
|
-
const DEFAULT_NAMESPACE$
|
|
47649
|
+
const DEFAULT_NAMESPACE$8 = 'InviteModal';
|
|
47630
47650
|
addIcons({ personOutline, mailOutline, closeOutline, checkmarkCircleOutline });
|
|
47631
47651
|
/**
|
|
47632
47652
|
* `val-invite-member-modal` — invitación de miembros a una organización.
|
|
@@ -47657,7 +47677,7 @@ class InviteMemberModalComponent {
|
|
|
47657
47677
|
/** Ids de miembros ya existentes (excluidos de los resultados). */
|
|
47658
47678
|
this.existingMemberIds = [];
|
|
47659
47679
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47660
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
47680
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$8;
|
|
47661
47681
|
this.query = signal('');
|
|
47662
47682
|
this.searching = signal(false);
|
|
47663
47683
|
this.searchResults = signal([]);
|
|
@@ -47704,8 +47724,8 @@ class InviteMemberModalComponent {
|
|
|
47704
47724
|
state: this.sending() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47705
47725
|
}));
|
|
47706
47726
|
this.searchSubject = new Subject();
|
|
47707
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
47708
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
47727
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$8)) {
|
|
47728
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$8, INVITE_MEMBER_MODAL_I18N);
|
|
47709
47729
|
}
|
|
47710
47730
|
this.loadRoles();
|
|
47711
47731
|
this.roleSub = this.roleControl.valueChanges.subscribe(v => {
|
|
@@ -48194,7 +48214,7 @@ const MEMBER_DETAIL_MODAL_I18N = {
|
|
|
48194
48214
|
},
|
|
48195
48215
|
};
|
|
48196
48216
|
|
|
48197
|
-
const DEFAULT_NAMESPACE$
|
|
48217
|
+
const DEFAULT_NAMESPACE$7 = 'Settings.MemberDetail';
|
|
48198
48218
|
/**
|
|
48199
48219
|
* `val-member-detail-modal` — detalle de miembro de organización: perfil, rol y
|
|
48200
48220
|
* permisos. Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -48231,7 +48251,7 @@ class MemberDetailModalComponent {
|
|
|
48231
48251
|
{ id: 'admin', name: 'admin' },
|
|
48232
48252
|
];
|
|
48233
48253
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48234
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
48254
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$7;
|
|
48235
48255
|
this.working = signal(false);
|
|
48236
48256
|
this.currentRole = signal('');
|
|
48237
48257
|
this.roleControl = new FormControl('');
|
|
@@ -48271,8 +48291,8 @@ class MemberDetailModalComponent {
|
|
|
48271
48291
|
type: 'button',
|
|
48272
48292
|
state: this.working() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48273
48293
|
}));
|
|
48274
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
48275
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
48294
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$7)) {
|
|
48295
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$7, MEMBER_DETAIL_MODAL_I18N);
|
|
48276
48296
|
}
|
|
48277
48297
|
}
|
|
48278
48298
|
ngOnInit() {
|
|
@@ -48609,7 +48629,7 @@ const TRANSFER_OWNERSHIP_MODAL_I18N = {
|
|
|
48609
48629
|
},
|
|
48610
48630
|
};
|
|
48611
48631
|
|
|
48612
|
-
const DEFAULT_NAMESPACE$
|
|
48632
|
+
const DEFAULT_NAMESPACE$6 = 'Settings.TransferModal';
|
|
48613
48633
|
/**
|
|
48614
48634
|
* `val-transfer-ownership-modal` — selector de miembro para transferir la
|
|
48615
48635
|
* propiedad de la organización. Promovido desde `showcase` bajo el proceso de
|
|
@@ -48633,7 +48653,7 @@ class TransferOwnershipModalComponent {
|
|
|
48633
48653
|
/** Lista de miembros transferibles (todos excepto el owner actual). */
|
|
48634
48654
|
this.members = [];
|
|
48635
48655
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48636
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
48656
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$6;
|
|
48637
48657
|
this.query = signal('');
|
|
48638
48658
|
this.selectedId = signal('');
|
|
48639
48659
|
this.filtered = computed(() => {
|
|
@@ -48645,8 +48665,8 @@ class TransferOwnershipModalComponent {
|
|
|
48645
48665
|
m.userId.toLowerCase().includes(q));
|
|
48646
48666
|
});
|
|
48647
48667
|
this.noResultsLabel = computed(() => `${this.t('noResults')} "${this.query()}"`);
|
|
48648
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
48649
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
48668
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$6)) {
|
|
48669
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$6, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48650
48670
|
}
|
|
48651
48671
|
}
|
|
48652
48672
|
ngOnInit() {
|
|
@@ -48831,6 +48851,849 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
48831
48851
|
type: Input
|
|
48832
48852
|
}] } });
|
|
48833
48853
|
|
|
48854
|
+
/**
|
|
48855
|
+
* Defaults i18n (es/en) embebidos en `val-member-import-modal` (ADR-023).
|
|
48856
|
+
* Auto-registrados si el consumer no proveyó el namespace `Settings.ImportModal`.
|
|
48857
|
+
*/
|
|
48858
|
+
const MEMBER_IMPORT_MODAL_I18N = {
|
|
48859
|
+
es: {
|
|
48860
|
+
title: 'Importar miembros',
|
|
48861
|
+
hint: 'Pega un CSV con columnas: email, nombre, rol (una fila por persona).',
|
|
48862
|
+
csvPlaceholder: 'email,nombre,rol\nana@x.com,Ana,editor\nbeto@x.com,Beto,viewer',
|
|
48863
|
+
rolesAvailable: 'Roles disponibles:',
|
|
48864
|
+
onConflictLabel: 'Si el email ya existe',
|
|
48865
|
+
conflictAssign: 'Asignar el rol',
|
|
48866
|
+
conflictSkip: 'Omitir',
|
|
48867
|
+
conflictError: 'Marcar error',
|
|
48868
|
+
sendActivation: 'Enviar email de activación a las cuentas nuevas',
|
|
48869
|
+
submit: 'Importar',
|
|
48870
|
+
submitting: 'Importando...',
|
|
48871
|
+
parseError: 'No se pudo interpretar el CSV. Revisa el formato.',
|
|
48872
|
+
noRows: 'Pega al menos una fila válida (email y rol).',
|
|
48873
|
+
summary: 'Resumen',
|
|
48874
|
+
created: 'creados',
|
|
48875
|
+
assigned: 'asignados',
|
|
48876
|
+
skipped: 'omitidos',
|
|
48877
|
+
failed: 'con error',
|
|
48878
|
+
colEmail: 'Email',
|
|
48879
|
+
colStatus: 'Estado',
|
|
48880
|
+
colDetail: 'Detalle',
|
|
48881
|
+
activationSent: 'activación enviada',
|
|
48882
|
+
activationPending: 'activación pendiente',
|
|
48883
|
+
again: 'Importar otro lote',
|
|
48884
|
+
close: 'Cerrar',
|
|
48885
|
+
genericError: 'No se pudo completar la importación. Intenta de nuevo.',
|
|
48886
|
+
},
|
|
48887
|
+
en: {
|
|
48888
|
+
title: 'Import members',
|
|
48889
|
+
hint: 'Paste a CSV with columns: email, name, role (one row per person).',
|
|
48890
|
+
csvPlaceholder: 'email,name,role\nana@x.com,Ana,editor\nbeto@x.com,Beto,viewer',
|
|
48891
|
+
rolesAvailable: 'Available roles:',
|
|
48892
|
+
onConflictLabel: 'If the email already exists',
|
|
48893
|
+
conflictAssign: 'Assign the role',
|
|
48894
|
+
conflictSkip: 'Skip',
|
|
48895
|
+
conflictError: 'Mark as error',
|
|
48896
|
+
sendActivation: 'Send activation email to new accounts',
|
|
48897
|
+
submit: 'Import',
|
|
48898
|
+
submitting: 'Importing...',
|
|
48899
|
+
parseError: "Couldn't parse the CSV. Check the format.",
|
|
48900
|
+
noRows: 'Paste at least one valid row (email and role).',
|
|
48901
|
+
summary: 'Summary',
|
|
48902
|
+
created: 'created',
|
|
48903
|
+
assigned: 'assigned',
|
|
48904
|
+
skipped: 'skipped',
|
|
48905
|
+
failed: 'failed',
|
|
48906
|
+
colEmail: 'Email',
|
|
48907
|
+
colStatus: 'Status',
|
|
48908
|
+
colDetail: 'Detail',
|
|
48909
|
+
activationSent: 'activation sent',
|
|
48910
|
+
activationPending: 'activation pending',
|
|
48911
|
+
again: 'Import another batch',
|
|
48912
|
+
close: 'Close',
|
|
48913
|
+
genericError: "Couldn't complete the import. Try again.",
|
|
48914
|
+
},
|
|
48915
|
+
};
|
|
48916
|
+
|
|
48917
|
+
const DEFAULT_NAMESPACE$5 = 'Settings.ImportModal';
|
|
48918
|
+
/**
|
|
48919
|
+
* `val-member-import-modal` — panel de carga masiva de miembros (ADR-023 fase 6).
|
|
48920
|
+
*
|
|
48921
|
+
* El admin pega un CSV (`email,nombre,rol`); el modal lo parsea a filas y llama
|
|
48922
|
+
* `OrgService.importMembers`. Muestra el resultado por-fila (partial success):
|
|
48923
|
+
* `created` / `assigned` / `skipped` / `error`. Header canónico (Regla #5).
|
|
48924
|
+
*
|
|
48925
|
+
* Auto-registra defaults i18n (es/en) en `Settings.ImportModal`.
|
|
48926
|
+
*/
|
|
48927
|
+
class MemberImportModalComponent {
|
|
48928
|
+
constructor() {
|
|
48929
|
+
this.i18n = inject(I18nService);
|
|
48930
|
+
this.orgService = inject(OrgService);
|
|
48931
|
+
/** Org destino del import. */
|
|
48932
|
+
this.orgId = '';
|
|
48933
|
+
/** Nombres de roles disponibles (para el hint). Opcional. */
|
|
48934
|
+
this.availableRoles = [];
|
|
48935
|
+
/** Namespace i18n. */
|
|
48936
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$5;
|
|
48937
|
+
this.csv = '';
|
|
48938
|
+
this.onConflict = 'assignRole';
|
|
48939
|
+
this.sendActivation = true;
|
|
48940
|
+
this.submitting = signal(false);
|
|
48941
|
+
this.errorMsg = signal('');
|
|
48942
|
+
this.results = signal(null);
|
|
48943
|
+
this.rolesHint = computed(() => this.availableRoles.length ? `${this.t('rolesAvailable')} ${this.availableRoles.join(', ')}` : '');
|
|
48944
|
+
this.summaryLabel = computed(() => {
|
|
48945
|
+
const s = this.results()?.summary;
|
|
48946
|
+
if (!s)
|
|
48947
|
+
return this.t('summary');
|
|
48948
|
+
return `${this.t('summary')}: ${s.created} ${this.t('created')} · ${s.assigned} ${this.t('assigned')} · ${s.skipped} ${this.t('skipped')} · ${s.failed} ${this.t('failed')}`;
|
|
48949
|
+
});
|
|
48950
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$5)) {
|
|
48951
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$5, MEMBER_IMPORT_MODAL_I18N);
|
|
48952
|
+
}
|
|
48953
|
+
}
|
|
48954
|
+
ngOnInit() {
|
|
48955
|
+
if (!this.i18n.hasNamespace(this.i18nNamespace)) {
|
|
48956
|
+
this.i18n.registerContent(this.i18nNamespace, MEMBER_IMPORT_MODAL_I18N);
|
|
48957
|
+
}
|
|
48958
|
+
}
|
|
48959
|
+
/** Parsea el CSV pegado a filas {email,name,roleName}. Tolera header. */
|
|
48960
|
+
parseCsv() {
|
|
48961
|
+
const rows = [];
|
|
48962
|
+
for (const raw of this.csv.split(/\r?\n/)) {
|
|
48963
|
+
const line = raw.trim();
|
|
48964
|
+
if (!line)
|
|
48965
|
+
continue;
|
|
48966
|
+
const cols = line.split(',').map(c => c.trim());
|
|
48967
|
+
const email = (cols[0] ?? '').toLowerCase();
|
|
48968
|
+
// Saltar header (primera col "email") o líneas sin @.
|
|
48969
|
+
if (!email || !email.includes('@'))
|
|
48970
|
+
continue;
|
|
48971
|
+
rows.push({ email, name: cols[1] ?? '', roleName: cols[2] ?? '' });
|
|
48972
|
+
}
|
|
48973
|
+
return rows;
|
|
48974
|
+
}
|
|
48975
|
+
submit() {
|
|
48976
|
+
this.errorMsg.set('');
|
|
48977
|
+
const users = this.parseCsv();
|
|
48978
|
+
if (users.length === 0) {
|
|
48979
|
+
this.errorMsg.set(this.t('noRows'));
|
|
48980
|
+
return;
|
|
48981
|
+
}
|
|
48982
|
+
if (users.some(u => !u.roleName)) {
|
|
48983
|
+
this.errorMsg.set(this.t('parseError'));
|
|
48984
|
+
return;
|
|
48985
|
+
}
|
|
48986
|
+
this.submitting.set(true);
|
|
48987
|
+
this.orgService
|
|
48988
|
+
.importMembers(this.orgId, {
|
|
48989
|
+
users,
|
|
48990
|
+
onConflict: this.onConflict,
|
|
48991
|
+
sendActivation: this.sendActivation,
|
|
48992
|
+
})
|
|
48993
|
+
.subscribe({
|
|
48994
|
+
next: res => {
|
|
48995
|
+
this.submitting.set(false);
|
|
48996
|
+
this.results.set(res);
|
|
48997
|
+
// Refrescar lista del consumer si hubo altas/asignaciones efectivas.
|
|
48998
|
+
if (res.summary.created + res.summary.assigned > 0) {
|
|
48999
|
+
this.onSuccess?.();
|
|
49000
|
+
}
|
|
49001
|
+
},
|
|
49002
|
+
error: err => {
|
|
49003
|
+
this.submitting.set(false);
|
|
49004
|
+
this.errorMsg.set(err?.error?.message ?? this.t('genericError'));
|
|
49005
|
+
},
|
|
49006
|
+
});
|
|
49007
|
+
}
|
|
49008
|
+
statusLabel(r) {
|
|
49009
|
+
const base = this.t(r.status === 'error' ? 'failed' : r.status);
|
|
49010
|
+
if (r.status === 'created' && r.activation) {
|
|
49011
|
+
return `${base} · ${this.t(r.activation === 'sent' ? 'activationSent' : 'activationPending')}`;
|
|
49012
|
+
}
|
|
49013
|
+
return base;
|
|
49014
|
+
}
|
|
49015
|
+
reset() {
|
|
49016
|
+
this.csv = '';
|
|
49017
|
+
this.errorMsg.set('');
|
|
49018
|
+
this.results.set(null);
|
|
49019
|
+
}
|
|
49020
|
+
dismiss() {
|
|
49021
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
49022
|
+
}
|
|
49023
|
+
t(key) {
|
|
49024
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
49025
|
+
}
|
|
49026
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MemberImportModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
49027
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: MemberImportModalComponent, isStandalone: true, selector: "val-member-import-modal", inputs: { orgId: "orgId", availableRoles: "availableRoles", onSuccess: "onSuccess", _modalRef: "_modalRef", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
49028
|
+
<ion-header>
|
|
49029
|
+
<ion-toolbar>
|
|
49030
|
+
<ion-buttons slot="end">
|
|
49031
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
49032
|
+
<strong>{{ t('close') }}</strong>
|
|
49033
|
+
</ion-button>
|
|
49034
|
+
</ion-buttons>
|
|
49035
|
+
</ion-toolbar>
|
|
49036
|
+
</ion-header>
|
|
49037
|
+
|
|
49038
|
+
<ion-content class="ion-padding">
|
|
49039
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
49040
|
+
|
|
49041
|
+
@if (!results()) {
|
|
49042
|
+
<val-title [props]="{ content: t('hint'), size: 'large', color: '', bold: false }" />
|
|
49043
|
+
|
|
49044
|
+
@if (rolesHint()) {
|
|
49045
|
+
<val-text [props]="{ content: rolesHint(), size: 'small', color: 'medium', bold: false }" />
|
|
49046
|
+
}
|
|
49047
|
+
|
|
49048
|
+
<ion-textarea
|
|
49049
|
+
class="import-csv"
|
|
49050
|
+
[autoGrow]="true"
|
|
49051
|
+
[rows]="6"
|
|
49052
|
+
[placeholder]="t('csvPlaceholder')"
|
|
49053
|
+
[(ngModel)]="csv"
|
|
49054
|
+
/>
|
|
49055
|
+
|
|
49056
|
+
<ion-select
|
|
49057
|
+
class="import-conflict"
|
|
49058
|
+
label="{{ t('onConflictLabel') }}"
|
|
49059
|
+
labelPlacement="stacked"
|
|
49060
|
+
interface="popover"
|
|
49061
|
+
[(ngModel)]="onConflict"
|
|
49062
|
+
>
|
|
49063
|
+
<ion-select-option value="assignRole">{{ t('conflictAssign') }}</ion-select-option>
|
|
49064
|
+
<ion-select-option value="skip">{{ t('conflictSkip') }}</ion-select-option>
|
|
49065
|
+
<ion-select-option value="error">{{ t('conflictError') }}</ion-select-option>
|
|
49066
|
+
</ion-select>
|
|
49067
|
+
|
|
49068
|
+
<ion-checkbox class="import-activation" labelPlacement="end" [(ngModel)]="sendActivation">
|
|
49069
|
+
{{ t('sendActivation') }}
|
|
49070
|
+
</ion-checkbox>
|
|
49071
|
+
|
|
49072
|
+
@if (errorMsg()) {
|
|
49073
|
+
<p class="import-error">{{ errorMsg() }}</p>
|
|
49074
|
+
}
|
|
49075
|
+
|
|
49076
|
+
<div class="import-actions">
|
|
49077
|
+
<ion-button expand="block" color="dark" [disabled]="submitting()" (click)="submit()">
|
|
49078
|
+
@if (submitting()) {
|
|
49079
|
+
<ion-spinner name="dots" />
|
|
49080
|
+
{{ t('submitting') }}
|
|
49081
|
+
} @else {
|
|
49082
|
+
{{ t('submit') }}
|
|
49083
|
+
}
|
|
49084
|
+
</ion-button>
|
|
49085
|
+
</div>
|
|
49086
|
+
} @else {
|
|
49087
|
+
<!-- Resultados -->
|
|
49088
|
+
<val-title [props]="{ content: summaryLabel(), size: 'large', color: '', bold: true }" />
|
|
49089
|
+
<div class="import-results">
|
|
49090
|
+
@for (r of results()!.results; track r.email) {
|
|
49091
|
+
<div class="import-row import-row--{{ r.status }}">
|
|
49092
|
+
<span class="import-row__email">{{ r.email }}</span>
|
|
49093
|
+
<span class="import-row__status">{{ statusLabel(r) }}</span>
|
|
49094
|
+
@if (r.reason) {
|
|
49095
|
+
<span class="import-row__reason">{{ r.reason }}</span>
|
|
49096
|
+
}
|
|
49097
|
+
</div>
|
|
49098
|
+
}
|
|
49099
|
+
</div>
|
|
49100
|
+
<div class="import-actions">
|
|
49101
|
+
<ion-button expand="block" fill="outline" color="dark" (click)="reset()">
|
|
49102
|
+
{{ t('again') }}
|
|
49103
|
+
</ion-button>
|
|
49104
|
+
</div>
|
|
49105
|
+
}
|
|
49106
|
+
</ion-content>
|
|
49107
|
+
`, isInline: true, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:12px}.import-csv{--background: var(--ion-color-light);border-radius:10px;margin-bottom:16px;font-family:monospace;font-size:13px}.import-conflict{margin-bottom:12px}.import-activation{display:block;margin-bottom:16px;font-size:14px}.import-error{margin:0 0 12px;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.import-actions{margin-top:8px}.import-results{display:flex;flex-direction:column;gap:6px;margin:12px 0}.import-row{display:grid;grid-template-columns:1fr auto;grid-row-gap:2px;align-items:center;padding:10px 12px;border-radius:8px;border-left:3px solid var(--ion-color-medium);background:var(--ion-color-light);font-size:14px}.import-row--created{border-left-color:var(--ion-color-success, #2dd36f)}.import-row--assigned{border-left-color:var(--ion-color-primary, #7026df)}.import-row--skipped{border-left-color:var(--ion-color-medium, #92949c)}.import-row--error{border-left-color:var(--ion-color-danger, #c0392b)}.import-row__email{font-weight:600;color:var(--ion-color-dark)}.import-row__status{text-align:right;color:var(--ion-color-medium-shade, #6b6e76)}.import-row__reason{grid-column:1 / -1;font-size:12px;color:var(--ion-color-danger, #c0392b)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { 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"] }] }); }
|
|
49108
|
+
}
|
|
49109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MemberImportModalComponent, decorators: [{
|
|
49110
|
+
type: Component,
|
|
49111
|
+
args: [{ selector: 'val-member-import-modal', standalone: true, imports: [
|
|
49112
|
+
FormsModule,
|
|
49113
|
+
IonHeader,
|
|
49114
|
+
IonToolbar,
|
|
49115
|
+
IonButtons,
|
|
49116
|
+
IonButton,
|
|
49117
|
+
IonContent,
|
|
49118
|
+
IonTextarea,
|
|
49119
|
+
IonSelect,
|
|
49120
|
+
IonSelectOption,
|
|
49121
|
+
IonCheckbox,
|
|
49122
|
+
IonSpinner,
|
|
49123
|
+
DisplayComponent,
|
|
49124
|
+
TextComponent,
|
|
49125
|
+
TitleComponent,
|
|
49126
|
+
], template: `
|
|
49127
|
+
<ion-header>
|
|
49128
|
+
<ion-toolbar>
|
|
49129
|
+
<ion-buttons slot="end">
|
|
49130
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
49131
|
+
<strong>{{ t('close') }}</strong>
|
|
49132
|
+
</ion-button>
|
|
49133
|
+
</ion-buttons>
|
|
49134
|
+
</ion-toolbar>
|
|
49135
|
+
</ion-header>
|
|
49136
|
+
|
|
49137
|
+
<ion-content class="ion-padding">
|
|
49138
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
49139
|
+
|
|
49140
|
+
@if (!results()) {
|
|
49141
|
+
<val-title [props]="{ content: t('hint'), size: 'large', color: '', bold: false }" />
|
|
49142
|
+
|
|
49143
|
+
@if (rolesHint()) {
|
|
49144
|
+
<val-text [props]="{ content: rolesHint(), size: 'small', color: 'medium', bold: false }" />
|
|
49145
|
+
}
|
|
49146
|
+
|
|
49147
|
+
<ion-textarea
|
|
49148
|
+
class="import-csv"
|
|
49149
|
+
[autoGrow]="true"
|
|
49150
|
+
[rows]="6"
|
|
49151
|
+
[placeholder]="t('csvPlaceholder')"
|
|
49152
|
+
[(ngModel)]="csv"
|
|
49153
|
+
/>
|
|
49154
|
+
|
|
49155
|
+
<ion-select
|
|
49156
|
+
class="import-conflict"
|
|
49157
|
+
label="{{ t('onConflictLabel') }}"
|
|
49158
|
+
labelPlacement="stacked"
|
|
49159
|
+
interface="popover"
|
|
49160
|
+
[(ngModel)]="onConflict"
|
|
49161
|
+
>
|
|
49162
|
+
<ion-select-option value="assignRole">{{ t('conflictAssign') }}</ion-select-option>
|
|
49163
|
+
<ion-select-option value="skip">{{ t('conflictSkip') }}</ion-select-option>
|
|
49164
|
+
<ion-select-option value="error">{{ t('conflictError') }}</ion-select-option>
|
|
49165
|
+
</ion-select>
|
|
49166
|
+
|
|
49167
|
+
<ion-checkbox class="import-activation" labelPlacement="end" [(ngModel)]="sendActivation">
|
|
49168
|
+
{{ t('sendActivation') }}
|
|
49169
|
+
</ion-checkbox>
|
|
49170
|
+
|
|
49171
|
+
@if (errorMsg()) {
|
|
49172
|
+
<p class="import-error">{{ errorMsg() }}</p>
|
|
49173
|
+
}
|
|
49174
|
+
|
|
49175
|
+
<div class="import-actions">
|
|
49176
|
+
<ion-button expand="block" color="dark" [disabled]="submitting()" (click)="submit()">
|
|
49177
|
+
@if (submitting()) {
|
|
49178
|
+
<ion-spinner name="dots" />
|
|
49179
|
+
{{ t('submitting') }}
|
|
49180
|
+
} @else {
|
|
49181
|
+
{{ t('submit') }}
|
|
49182
|
+
}
|
|
49183
|
+
</ion-button>
|
|
49184
|
+
</div>
|
|
49185
|
+
} @else {
|
|
49186
|
+
<!-- Resultados -->
|
|
49187
|
+
<val-title [props]="{ content: summaryLabel(), size: 'large', color: '', bold: true }" />
|
|
49188
|
+
<div class="import-results">
|
|
49189
|
+
@for (r of results()!.results; track r.email) {
|
|
49190
|
+
<div class="import-row import-row--{{ r.status }}">
|
|
49191
|
+
<span class="import-row__email">{{ r.email }}</span>
|
|
49192
|
+
<span class="import-row__status">{{ statusLabel(r) }}</span>
|
|
49193
|
+
@if (r.reason) {
|
|
49194
|
+
<span class="import-row__reason">{{ r.reason }}</span>
|
|
49195
|
+
}
|
|
49196
|
+
</div>
|
|
49197
|
+
}
|
|
49198
|
+
</div>
|
|
49199
|
+
<div class="import-actions">
|
|
49200
|
+
<ion-button expand="block" fill="outline" color="dark" (click)="reset()">
|
|
49201
|
+
{{ t('again') }}
|
|
49202
|
+
</ion-button>
|
|
49203
|
+
</div>
|
|
49204
|
+
}
|
|
49205
|
+
</ion-content>
|
|
49206
|
+
`, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:12px}.import-csv{--background: var(--ion-color-light);border-radius:10px;margin-bottom:16px;font-family:monospace;font-size:13px}.import-conflict{margin-bottom:12px}.import-activation{display:block;margin-bottom:16px;font-size:14px}.import-error{margin:0 0 12px;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.import-actions{margin-top:8px}.import-results{display:flex;flex-direction:column;gap:6px;margin:12px 0}.import-row{display:grid;grid-template-columns:1fr auto;grid-row-gap:2px;align-items:center;padding:10px 12px;border-radius:8px;border-left:3px solid var(--ion-color-medium);background:var(--ion-color-light);font-size:14px}.import-row--created{border-left-color:var(--ion-color-success, #2dd36f)}.import-row--assigned{border-left-color:var(--ion-color-primary, #7026df)}.import-row--skipped{border-left-color:var(--ion-color-medium, #92949c)}.import-row--error{border-left-color:var(--ion-color-danger, #c0392b)}.import-row__email{font-weight:600;color:var(--ion-color-dark)}.import-row__status{text-align:right;color:var(--ion-color-medium-shade, #6b6e76)}.import-row__reason{grid-column:1 / -1;font-size:12px;color:var(--ion-color-danger, #c0392b)}\n"] }]
|
|
49207
|
+
}], ctorParameters: () => [], propDecorators: { orgId: [{
|
|
49208
|
+
type: Input
|
|
49209
|
+
}], availableRoles: [{
|
|
49210
|
+
type: Input
|
|
49211
|
+
}], onSuccess: [{
|
|
49212
|
+
type: Input
|
|
49213
|
+
}], _modalRef: [{
|
|
49214
|
+
type: Input
|
|
49215
|
+
}], i18nNamespace: [{
|
|
49216
|
+
type: Input
|
|
49217
|
+
}] } });
|
|
49218
|
+
|
|
49219
|
+
/**
|
|
49220
|
+
* Cliente HTTP de Client API Keys org-scopeadas (ADR-023). La org activa se
|
|
49221
|
+
* resuelve en backend desde el JWT, así que el path no la incluye.
|
|
49222
|
+
*/
|
|
49223
|
+
class ApiKeyService {
|
|
49224
|
+
constructor(config, http) {
|
|
49225
|
+
this.config = config;
|
|
49226
|
+
this.http = http;
|
|
49227
|
+
}
|
|
49228
|
+
get baseUrl() {
|
|
49229
|
+
return `${this.config.apiUrl}/org/api-keys`;
|
|
49230
|
+
}
|
|
49231
|
+
/** Lista las API keys de la org activa. */
|
|
49232
|
+
list() {
|
|
49233
|
+
return this.http.get(`${this.baseUrl}/`).pipe(map$1(r => r.keys ?? []));
|
|
49234
|
+
}
|
|
49235
|
+
/** Crea una API key. La respuesta incluye el secreto (se muestra UNA vez). */
|
|
49236
|
+
create(req) {
|
|
49237
|
+
return this.http.post(`${this.baseUrl}/`, req);
|
|
49238
|
+
}
|
|
49239
|
+
/** Revoca (elimina) una API key por id. */
|
|
49240
|
+
revoke(keyId) {
|
|
49241
|
+
return this.http.delete(`${this.baseUrl}/${keyId}`);
|
|
49242
|
+
}
|
|
49243
|
+
/** Catálogo de permisos asignables a una key. */
|
|
49244
|
+
availablePermissions() {
|
|
49245
|
+
return this.http
|
|
49246
|
+
.get(`${this.baseUrl}/permissions`)
|
|
49247
|
+
.pipe(map$1(r => r.permissions ?? []));
|
|
49248
|
+
}
|
|
49249
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ApiKeyService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: i1$3.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
49250
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ApiKeyService, providedIn: 'root' }); }
|
|
49251
|
+
}
|
|
49252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ApiKeyService, decorators: [{
|
|
49253
|
+
type: Injectable,
|
|
49254
|
+
args: [{ providedIn: 'root' }]
|
|
49255
|
+
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
49256
|
+
type: Inject,
|
|
49257
|
+
args: [VALTECH_AUTH_CONFIG]
|
|
49258
|
+
}] }, { type: i1$3.HttpClient }] });
|
|
49259
|
+
|
|
49260
|
+
/**
|
|
49261
|
+
* Defaults i18n (es/en) embebidos en `val-api-keys-modal` (ADR-023).
|
|
49262
|
+
* Auto-registrados si el consumer no proveyó el namespace `Settings.ApiKeysModal`.
|
|
49263
|
+
*/
|
|
49264
|
+
const API_KEYS_MODAL_I18N = {
|
|
49265
|
+
es: {
|
|
49266
|
+
title: 'Client API Keys',
|
|
49267
|
+
hint: 'Llaves M2M org-scopeadas para integraciones (p. ej. importar miembros).',
|
|
49268
|
+
empty: 'Aún no hay API keys en esta organización.',
|
|
49269
|
+
newKey: 'Nueva API key',
|
|
49270
|
+
nameLabel: 'Nombre',
|
|
49271
|
+
namePlaceholder: 'Ej: Integración RRHH',
|
|
49272
|
+
permissionsLabel: 'Permisos',
|
|
49273
|
+
expiresLabel: 'Expira en (días, opcional)',
|
|
49274
|
+
create: 'Crear key',
|
|
49275
|
+
creating: 'Creando...',
|
|
49276
|
+
cancel: 'Cancelar',
|
|
49277
|
+
revoke: 'Revocar',
|
|
49278
|
+
revokeConfirm: '¿Revocar esta API key? Las integraciones que la usen dejarán de funcionar.',
|
|
49279
|
+
secretTitle: 'Copia tu API key ahora',
|
|
49280
|
+
secretWarning: 'Este secreto se muestra una sola vez. Guárdalo en un lugar seguro.',
|
|
49281
|
+
copy: 'Copiar',
|
|
49282
|
+
copied: 'Copiada',
|
|
49283
|
+
done: 'Listo',
|
|
49284
|
+
statusActive: 'activa',
|
|
49285
|
+
lastUsed: 'Último uso',
|
|
49286
|
+
never: 'nunca',
|
|
49287
|
+
permsCount: 'permisos',
|
|
49288
|
+
noName: 'El nombre es obligatorio.',
|
|
49289
|
+
noPerms: 'Selecciona al menos un permiso.',
|
|
49290
|
+
close: 'Cerrar',
|
|
49291
|
+
genericError: 'No se pudo completar la operación. Intenta de nuevo.',
|
|
49292
|
+
},
|
|
49293
|
+
en: {
|
|
49294
|
+
title: 'Client API Keys',
|
|
49295
|
+
hint: 'Org-scoped M2M keys for integrations (e.g. member import).',
|
|
49296
|
+
empty: 'No API keys in this organization yet.',
|
|
49297
|
+
newKey: 'New API key',
|
|
49298
|
+
nameLabel: 'Name',
|
|
49299
|
+
namePlaceholder: 'E.g: HR integration',
|
|
49300
|
+
permissionsLabel: 'Permissions',
|
|
49301
|
+
expiresLabel: 'Expires in (days, optional)',
|
|
49302
|
+
create: 'Create key',
|
|
49303
|
+
creating: 'Creating...',
|
|
49304
|
+
cancel: 'Cancel',
|
|
49305
|
+
revoke: 'Revoke',
|
|
49306
|
+
revokeConfirm: 'Revoke this API key? Integrations using it will stop working.',
|
|
49307
|
+
secretTitle: 'Copy your API key now',
|
|
49308
|
+
secretWarning: 'This secret is shown only once. Store it somewhere safe.',
|
|
49309
|
+
copy: 'Copy',
|
|
49310
|
+
copied: 'Copied',
|
|
49311
|
+
done: 'Done',
|
|
49312
|
+
statusActive: 'active',
|
|
49313
|
+
lastUsed: 'Last used',
|
|
49314
|
+
never: 'never',
|
|
49315
|
+
permsCount: 'permissions',
|
|
49316
|
+
noName: 'Name is required.',
|
|
49317
|
+
noPerms: 'Select at least one permission.',
|
|
49318
|
+
close: 'Close',
|
|
49319
|
+
genericError: "Couldn't complete the operation. Try again.",
|
|
49320
|
+
},
|
|
49321
|
+
};
|
|
49322
|
+
|
|
49323
|
+
const DEFAULT_NAMESPACE$4 = 'Settings.ApiKeysModal';
|
|
49324
|
+
/**
|
|
49325
|
+
* `val-api-keys-modal` — gestión de Client API Keys org-scopeadas (ADR-023 fase 6).
|
|
49326
|
+
*
|
|
49327
|
+
* Lista las keys de la org, permite crear (mostrando el secreto UNA vez con copia)
|
|
49328
|
+
* y revocar. Pensado para habilitar integraciones M2M del import de miembros, pero
|
|
49329
|
+
* sirve a cualquier permiso del catálogo. Header canónico (Regla #5).
|
|
49330
|
+
*/
|
|
49331
|
+
class ApiKeysModalComponent {
|
|
49332
|
+
constructor() {
|
|
49333
|
+
this.i18n = inject(I18nService);
|
|
49334
|
+
this.apiKeys = inject(ApiKeyService);
|
|
49335
|
+
/** Namespace i18n. */
|
|
49336
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$4;
|
|
49337
|
+
this.keys = signal([]);
|
|
49338
|
+
this.availablePermissions = signal([]);
|
|
49339
|
+
this.loading = signal(true);
|
|
49340
|
+
this.showCreate = signal(false);
|
|
49341
|
+
this.submitting = signal(false);
|
|
49342
|
+
this.errorMsg = signal('');
|
|
49343
|
+
this.secret = signal(null);
|
|
49344
|
+
this.copied = signal(false);
|
|
49345
|
+
this.name = '';
|
|
49346
|
+
this.expiresInDays = null;
|
|
49347
|
+
this.selectedPerms = signal(new Set());
|
|
49348
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$4)) {
|
|
49349
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$4, API_KEYS_MODAL_I18N);
|
|
49350
|
+
}
|
|
49351
|
+
}
|
|
49352
|
+
ngOnInit() {
|
|
49353
|
+
if (!this.i18n.hasNamespace(this.i18nNamespace)) {
|
|
49354
|
+
this.i18n.registerContent(this.i18nNamespace, API_KEYS_MODAL_I18N);
|
|
49355
|
+
}
|
|
49356
|
+
this.refresh();
|
|
49357
|
+
this.apiKeys.availablePermissions().subscribe({
|
|
49358
|
+
next: perms => this.availablePermissions.set(perms),
|
|
49359
|
+
error: () => { },
|
|
49360
|
+
});
|
|
49361
|
+
}
|
|
49362
|
+
refresh() {
|
|
49363
|
+
this.loading.set(true);
|
|
49364
|
+
this.apiKeys.list().subscribe({
|
|
49365
|
+
next: keys => {
|
|
49366
|
+
this.keys.set(keys);
|
|
49367
|
+
this.loading.set(false);
|
|
49368
|
+
},
|
|
49369
|
+
error: () => this.loading.set(false),
|
|
49370
|
+
});
|
|
49371
|
+
}
|
|
49372
|
+
openCreate() {
|
|
49373
|
+
this.errorMsg.set('');
|
|
49374
|
+
this.name = '';
|
|
49375
|
+
this.expiresInDays = null;
|
|
49376
|
+
this.selectedPerms.set(new Set());
|
|
49377
|
+
this.showCreate.set(true);
|
|
49378
|
+
}
|
|
49379
|
+
togglePerm(perm, ev) {
|
|
49380
|
+
const checked = ev.detail?.checked ?? false;
|
|
49381
|
+
const next = new Set(this.selectedPerms());
|
|
49382
|
+
if (checked) {
|
|
49383
|
+
next.add(perm);
|
|
49384
|
+
}
|
|
49385
|
+
else {
|
|
49386
|
+
next.delete(perm);
|
|
49387
|
+
}
|
|
49388
|
+
this.selectedPerms.set(next);
|
|
49389
|
+
}
|
|
49390
|
+
submit() {
|
|
49391
|
+
this.errorMsg.set('');
|
|
49392
|
+
if (!this.name.trim()) {
|
|
49393
|
+
this.errorMsg.set(this.t('noName'));
|
|
49394
|
+
return;
|
|
49395
|
+
}
|
|
49396
|
+
const permissions = Array.from(this.selectedPerms());
|
|
49397
|
+
if (permissions.length === 0) {
|
|
49398
|
+
this.errorMsg.set(this.t('noPerms'));
|
|
49399
|
+
return;
|
|
49400
|
+
}
|
|
49401
|
+
this.submitting.set(true);
|
|
49402
|
+
this.apiKeys
|
|
49403
|
+
.create({
|
|
49404
|
+
name: this.name.trim(),
|
|
49405
|
+
permissions,
|
|
49406
|
+
expiresInDays: this.expiresInDays && this.expiresInDays > 0 ? this.expiresInDays : undefined,
|
|
49407
|
+
})
|
|
49408
|
+
.subscribe({
|
|
49409
|
+
next: res => {
|
|
49410
|
+
this.submitting.set(false);
|
|
49411
|
+
this.showCreate.set(false);
|
|
49412
|
+
this.secret.set(res.key);
|
|
49413
|
+
},
|
|
49414
|
+
error: err => {
|
|
49415
|
+
this.submitting.set(false);
|
|
49416
|
+
this.errorMsg.set(err?.error?.message ?? this.t('genericError'));
|
|
49417
|
+
},
|
|
49418
|
+
});
|
|
49419
|
+
}
|
|
49420
|
+
revoke(key) {
|
|
49421
|
+
if (!confirm(this.t('revokeConfirm')))
|
|
49422
|
+
return;
|
|
49423
|
+
this.apiKeys.revoke(key.keyId).subscribe({
|
|
49424
|
+
next: () => this.refresh(),
|
|
49425
|
+
error: err => this.errorMsg.set(err?.error?.message ?? this.t('genericError')),
|
|
49426
|
+
});
|
|
49427
|
+
}
|
|
49428
|
+
async copy(secret) {
|
|
49429
|
+
try {
|
|
49430
|
+
await navigator.clipboard.writeText(secret);
|
|
49431
|
+
this.copied.set(true);
|
|
49432
|
+
}
|
|
49433
|
+
catch {
|
|
49434
|
+
// clipboard no disponible — el user puede seleccionar el texto manualmente
|
|
49435
|
+
}
|
|
49436
|
+
}
|
|
49437
|
+
finishSecret() {
|
|
49438
|
+
this.secret.set(null);
|
|
49439
|
+
this.copied.set(false);
|
|
49440
|
+
this.refresh();
|
|
49441
|
+
}
|
|
49442
|
+
dismiss() {
|
|
49443
|
+
this._modalRef?.dismiss(null, 'cancel');
|
|
49444
|
+
}
|
|
49445
|
+
t(key) {
|
|
49446
|
+
return this.i18n.t(key, this.i18nNamespace);
|
|
49447
|
+
}
|
|
49448
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ApiKeysModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
49449
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ApiKeysModalComponent, isStandalone: true, selector: "val-api-keys-modal", inputs: { _modalRef: "_modalRef", i18nNamespace: "i18nNamespace" }, ngImport: i0, template: `
|
|
49450
|
+
<ion-header>
|
|
49451
|
+
<ion-toolbar>
|
|
49452
|
+
<ion-buttons slot="end">
|
|
49453
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
49454
|
+
<strong>{{ t('close') }}</strong>
|
|
49455
|
+
</ion-button>
|
|
49456
|
+
</ion-buttons>
|
|
49457
|
+
</ion-toolbar>
|
|
49458
|
+
</ion-header>
|
|
49459
|
+
|
|
49460
|
+
<ion-content class="ion-padding">
|
|
49461
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
49462
|
+
<val-title [props]="{ content: t('hint'), size: 'large', color: '', bold: false }" />
|
|
49463
|
+
|
|
49464
|
+
@if (secret(); as s) {
|
|
49465
|
+
<!-- Secreto recién creado: mostrar UNA vez -->
|
|
49466
|
+
<div class="apikey-secret">
|
|
49467
|
+
<val-title [props]="{ content: t('secretTitle'), size: 'large', color: '', bold: true }" />
|
|
49468
|
+
<p class="apikey-secret__warn">{{ t('secretWarning') }}</p>
|
|
49469
|
+
<div class="apikey-secret__box">
|
|
49470
|
+
<code>{{ s.secret }}</code>
|
|
49471
|
+
</div>
|
|
49472
|
+
<div class="apikey-actions">
|
|
49473
|
+
<ion-button expand="block" color="dark" (click)="copy(s.secret)">
|
|
49474
|
+
{{ copied() ? t('copied') : t('copy') }}
|
|
49475
|
+
</ion-button>
|
|
49476
|
+
<ion-button expand="block" fill="outline" color="dark" (click)="finishSecret()">
|
|
49477
|
+
{{ t('done') }}
|
|
49478
|
+
</ion-button>
|
|
49479
|
+
</div>
|
|
49480
|
+
</div>
|
|
49481
|
+
} @else {
|
|
49482
|
+
@if (loading()) {
|
|
49483
|
+
<ion-spinner name="dots" />
|
|
49484
|
+
} @else {
|
|
49485
|
+
<!-- Lista -->
|
|
49486
|
+
@if (keys().length === 0) {
|
|
49487
|
+
<val-text [props]="{ content: t('empty'), size: 'medium', color: 'medium', bold: false }" />
|
|
49488
|
+
} @else {
|
|
49489
|
+
<div class="apikey-list">
|
|
49490
|
+
@for (k of keys(); track k.keyId) {
|
|
49491
|
+
<div class="apikey-row">
|
|
49492
|
+
<div class="apikey-row__main">
|
|
49493
|
+
<span class="apikey-row__name">{{ k.name }}</span>
|
|
49494
|
+
<span class="apikey-row__meta">
|
|
49495
|
+
{{ k.permissions.length }} {{ t('permsCount') }} · {{ t('lastUsed') }}:
|
|
49496
|
+
{{ k.lastUsedAt || t('never') }}
|
|
49497
|
+
</span>
|
|
49498
|
+
</div>
|
|
49499
|
+
<ion-button fill="clear" color="danger" size="small" (click)="revoke(k)">
|
|
49500
|
+
{{ t('revoke') }}
|
|
49501
|
+
</ion-button>
|
|
49502
|
+
</div>
|
|
49503
|
+
}
|
|
49504
|
+
</div>
|
|
49505
|
+
}
|
|
49506
|
+
|
|
49507
|
+
@if (errorMsg()) {
|
|
49508
|
+
<p class="apikey-error">{{ errorMsg() }}</p>
|
|
49509
|
+
}
|
|
49510
|
+
|
|
49511
|
+
<!-- Crear -->
|
|
49512
|
+
@if (showCreate()) {
|
|
49513
|
+
<div class="apikey-create">
|
|
49514
|
+
<ion-input
|
|
49515
|
+
label="{{ t('nameLabel') }}"
|
|
49516
|
+
labelPlacement="stacked"
|
|
49517
|
+
[placeholder]="t('namePlaceholder')"
|
|
49518
|
+
[(ngModel)]="name"
|
|
49519
|
+
/>
|
|
49520
|
+
<p class="apikey-create__label">{{ t('permissionsLabel') }}</p>
|
|
49521
|
+
<div class="apikey-perms">
|
|
49522
|
+
@for (p of availablePermissions(); track p) {
|
|
49523
|
+
<ion-checkbox
|
|
49524
|
+
labelPlacement="end"
|
|
49525
|
+
[checked]="selectedPerms().has(p)"
|
|
49526
|
+
(ionChange)="togglePerm(p, $event)"
|
|
49527
|
+
>
|
|
49528
|
+
{{ p }}
|
|
49529
|
+
</ion-checkbox>
|
|
49530
|
+
}
|
|
49531
|
+
</div>
|
|
49532
|
+
<ion-input
|
|
49533
|
+
label="{{ t('expiresLabel') }}"
|
|
49534
|
+
labelPlacement="stacked"
|
|
49535
|
+
type="number"
|
|
49536
|
+
[(ngModel)]="expiresInDays"
|
|
49537
|
+
/>
|
|
49538
|
+
<div class="apikey-actions">
|
|
49539
|
+
<ion-button expand="block" color="dark" [disabled]="submitting()" (click)="submit()">
|
|
49540
|
+
@if (submitting()) {
|
|
49541
|
+
<ion-spinner name="dots" /> {{ t('creating') }}
|
|
49542
|
+
} @else {
|
|
49543
|
+
{{ t('create') }}
|
|
49544
|
+
}
|
|
49545
|
+
</ion-button>
|
|
49546
|
+
<ion-button expand="block" fill="clear" color="medium" (click)="showCreate.set(false)">
|
|
49547
|
+
{{ t('cancel') }}
|
|
49548
|
+
</ion-button>
|
|
49549
|
+
</div>
|
|
49550
|
+
</div>
|
|
49551
|
+
} @else {
|
|
49552
|
+
<div class="apikey-actions">
|
|
49553
|
+
<ion-button expand="block" color="primary" (click)="openCreate()">
|
|
49554
|
+
{{ t('newKey') }}
|
|
49555
|
+
</ion-button>
|
|
49556
|
+
</div>
|
|
49557
|
+
}
|
|
49558
|
+
}
|
|
49559
|
+
}
|
|
49560
|
+
</ion-content>
|
|
49561
|
+
`, isInline: true, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:12px}.apikey-list{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}.apikey-row{display:flex;align-items:center;justify-content:space-between;padding:12px;border-radius:10px;border:1.5px solid var(--ion-color-light)}.apikey-row__main{display:flex;flex-direction:column}.apikey-row__name{font-weight:600;color:var(--ion-color-dark)}.apikey-row__meta{font-size:12px;color:var(--ion-color-medium-shade, #6b6e76)}.apikey-create{margin-top:8px;padding:16px;border-radius:12px;background:var(--ion-color-light)}.apikey-create__label{margin:12px 0 4px;font-size:13px;font-weight:600;color:var(--ion-color-dark)}.apikey-perms{display:flex;flex-direction:column;gap:6px;margin-bottom:12px;font-size:13px}.apikey-actions{margin-top:16px;display:flex;flex-direction:column;gap:8px}.apikey-error{margin:8px 0;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.apikey-secret__warn{font-size:.875rem;color:var(--ion-color-warning-shade, #b88600);margin:0 0 12px}.apikey-secret__box{padding:12px;border-radius:8px;background:var(--ion-color-dark);color:#fff;word-break:break-all;font-family:monospace;font-size:13px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { 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"] }] }); }
|
|
49562
|
+
}
|
|
49563
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ApiKeysModalComponent, decorators: [{
|
|
49564
|
+
type: Component,
|
|
49565
|
+
args: [{ selector: 'val-api-keys-modal', standalone: true, imports: [
|
|
49566
|
+
FormsModule,
|
|
49567
|
+
IonHeader,
|
|
49568
|
+
IonToolbar,
|
|
49569
|
+
IonButtons,
|
|
49570
|
+
IonButton,
|
|
49571
|
+
IonContent,
|
|
49572
|
+
IonInput,
|
|
49573
|
+
IonCheckbox,
|
|
49574
|
+
IonSpinner,
|
|
49575
|
+
DisplayComponent,
|
|
49576
|
+
TextComponent,
|
|
49577
|
+
TitleComponent,
|
|
49578
|
+
], template: `
|
|
49579
|
+
<ion-header>
|
|
49580
|
+
<ion-toolbar>
|
|
49581
|
+
<ion-buttons slot="end">
|
|
49582
|
+
<ion-button fill="clear" color="dark" (click)="dismiss()">
|
|
49583
|
+
<strong>{{ t('close') }}</strong>
|
|
49584
|
+
</ion-button>
|
|
49585
|
+
</ion-buttons>
|
|
49586
|
+
</ion-toolbar>
|
|
49587
|
+
</ion-header>
|
|
49588
|
+
|
|
49589
|
+
<ion-content class="ion-padding">
|
|
49590
|
+
<val-display [props]="{ content: t('title'), size: 'small', color: 'dark' }" />
|
|
49591
|
+
<val-title [props]="{ content: t('hint'), size: 'large', color: '', bold: false }" />
|
|
49592
|
+
|
|
49593
|
+
@if (secret(); as s) {
|
|
49594
|
+
<!-- Secreto recién creado: mostrar UNA vez -->
|
|
49595
|
+
<div class="apikey-secret">
|
|
49596
|
+
<val-title [props]="{ content: t('secretTitle'), size: 'large', color: '', bold: true }" />
|
|
49597
|
+
<p class="apikey-secret__warn">{{ t('secretWarning') }}</p>
|
|
49598
|
+
<div class="apikey-secret__box">
|
|
49599
|
+
<code>{{ s.secret }}</code>
|
|
49600
|
+
</div>
|
|
49601
|
+
<div class="apikey-actions">
|
|
49602
|
+
<ion-button expand="block" color="dark" (click)="copy(s.secret)">
|
|
49603
|
+
{{ copied() ? t('copied') : t('copy') }}
|
|
49604
|
+
</ion-button>
|
|
49605
|
+
<ion-button expand="block" fill="outline" color="dark" (click)="finishSecret()">
|
|
49606
|
+
{{ t('done') }}
|
|
49607
|
+
</ion-button>
|
|
49608
|
+
</div>
|
|
49609
|
+
</div>
|
|
49610
|
+
} @else {
|
|
49611
|
+
@if (loading()) {
|
|
49612
|
+
<ion-spinner name="dots" />
|
|
49613
|
+
} @else {
|
|
49614
|
+
<!-- Lista -->
|
|
49615
|
+
@if (keys().length === 0) {
|
|
49616
|
+
<val-text [props]="{ content: t('empty'), size: 'medium', color: 'medium', bold: false }" />
|
|
49617
|
+
} @else {
|
|
49618
|
+
<div class="apikey-list">
|
|
49619
|
+
@for (k of keys(); track k.keyId) {
|
|
49620
|
+
<div class="apikey-row">
|
|
49621
|
+
<div class="apikey-row__main">
|
|
49622
|
+
<span class="apikey-row__name">{{ k.name }}</span>
|
|
49623
|
+
<span class="apikey-row__meta">
|
|
49624
|
+
{{ k.permissions.length }} {{ t('permsCount') }} · {{ t('lastUsed') }}:
|
|
49625
|
+
{{ k.lastUsedAt || t('never') }}
|
|
49626
|
+
</span>
|
|
49627
|
+
</div>
|
|
49628
|
+
<ion-button fill="clear" color="danger" size="small" (click)="revoke(k)">
|
|
49629
|
+
{{ t('revoke') }}
|
|
49630
|
+
</ion-button>
|
|
49631
|
+
</div>
|
|
49632
|
+
}
|
|
49633
|
+
</div>
|
|
49634
|
+
}
|
|
49635
|
+
|
|
49636
|
+
@if (errorMsg()) {
|
|
49637
|
+
<p class="apikey-error">{{ errorMsg() }}</p>
|
|
49638
|
+
}
|
|
49639
|
+
|
|
49640
|
+
<!-- Crear -->
|
|
49641
|
+
@if (showCreate()) {
|
|
49642
|
+
<div class="apikey-create">
|
|
49643
|
+
<ion-input
|
|
49644
|
+
label="{{ t('nameLabel') }}"
|
|
49645
|
+
labelPlacement="stacked"
|
|
49646
|
+
[placeholder]="t('namePlaceholder')"
|
|
49647
|
+
[(ngModel)]="name"
|
|
49648
|
+
/>
|
|
49649
|
+
<p class="apikey-create__label">{{ t('permissionsLabel') }}</p>
|
|
49650
|
+
<div class="apikey-perms">
|
|
49651
|
+
@for (p of availablePermissions(); track p) {
|
|
49652
|
+
<ion-checkbox
|
|
49653
|
+
labelPlacement="end"
|
|
49654
|
+
[checked]="selectedPerms().has(p)"
|
|
49655
|
+
(ionChange)="togglePerm(p, $event)"
|
|
49656
|
+
>
|
|
49657
|
+
{{ p }}
|
|
49658
|
+
</ion-checkbox>
|
|
49659
|
+
}
|
|
49660
|
+
</div>
|
|
49661
|
+
<ion-input
|
|
49662
|
+
label="{{ t('expiresLabel') }}"
|
|
49663
|
+
labelPlacement="stacked"
|
|
49664
|
+
type="number"
|
|
49665
|
+
[(ngModel)]="expiresInDays"
|
|
49666
|
+
/>
|
|
49667
|
+
<div class="apikey-actions">
|
|
49668
|
+
<ion-button expand="block" color="dark" [disabled]="submitting()" (click)="submit()">
|
|
49669
|
+
@if (submitting()) {
|
|
49670
|
+
<ion-spinner name="dots" /> {{ t('creating') }}
|
|
49671
|
+
} @else {
|
|
49672
|
+
{{ t('create') }}
|
|
49673
|
+
}
|
|
49674
|
+
</ion-button>
|
|
49675
|
+
<ion-button expand="block" fill="clear" color="medium" (click)="showCreate.set(false)">
|
|
49676
|
+
{{ t('cancel') }}
|
|
49677
|
+
</ion-button>
|
|
49678
|
+
</div>
|
|
49679
|
+
</div>
|
|
49680
|
+
} @else {
|
|
49681
|
+
<div class="apikey-actions">
|
|
49682
|
+
<ion-button expand="block" color="primary" (click)="openCreate()">
|
|
49683
|
+
{{ t('newKey') }}
|
|
49684
|
+
</ion-button>
|
|
49685
|
+
</div>
|
|
49686
|
+
}
|
|
49687
|
+
}
|
|
49688
|
+
}
|
|
49689
|
+
</ion-content>
|
|
49690
|
+
`, styles: ["val-display{display:block;margin-bottom:4px}val-title{display:block;margin-bottom:12px}.apikey-list{display:flex;flex-direction:column;gap:8px;margin-bottom:16px}.apikey-row{display:flex;align-items:center;justify-content:space-between;padding:12px;border-radius:10px;border:1.5px solid var(--ion-color-light)}.apikey-row__main{display:flex;flex-direction:column}.apikey-row__name{font-weight:600;color:var(--ion-color-dark)}.apikey-row__meta{font-size:12px;color:var(--ion-color-medium-shade, #6b6e76)}.apikey-create{margin-top:8px;padding:16px;border-radius:12px;background:var(--ion-color-light)}.apikey-create__label{margin:12px 0 4px;font-size:13px;font-weight:600;color:var(--ion-color-dark)}.apikey-perms{display:flex;flex-direction:column;gap:6px;margin-bottom:12px;font-size:13px}.apikey-actions{margin-top:16px;display:flex;flex-direction:column;gap:8px}.apikey-error{margin:8px 0;font-size:.875rem;color:var(--ion-color-danger, #c0392b)}.apikey-secret__warn{font-size:.875rem;color:var(--ion-color-warning-shade, #b88600);margin:0 0 12px}.apikey-secret__box{padding:12px;border-radius:8px;background:var(--ion-color-dark);color:#fff;word-break:break-all;font-family:monospace;font-size:13px}\n"] }]
|
|
49691
|
+
}], ctorParameters: () => [], propDecorators: { _modalRef: [{
|
|
49692
|
+
type: Input
|
|
49693
|
+
}], i18nNamespace: [{
|
|
49694
|
+
type: Input
|
|
49695
|
+
}] } });
|
|
49696
|
+
|
|
48834
49697
|
/**
|
|
48835
49698
|
* Defaults i18n (es/en) embebidos en `val-organization-view`. Auto-registrados en
|
|
48836
49699
|
* el constructor del componente si el consumer no proveyó el namespace
|
|
@@ -48886,6 +49749,8 @@ const ORGANIZATION_VIEW_I18N = {
|
|
|
48886
49749
|
inviteCtaTitle: '¿Deseas agregar a alguien?',
|
|
48887
49750
|
inviteCtaHint: 'Invita a usuarios a unirse a tu organización.',
|
|
48888
49751
|
inviteOpen: 'Invitar',
|
|
49752
|
+
importOpen: 'Importar',
|
|
49753
|
+
apiKeysOpen: 'API Keys',
|
|
48889
49754
|
viewMemberCta: 'Ver miembro',
|
|
48890
49755
|
roleViewer: 'Visor',
|
|
48891
49756
|
roleEditor: 'Editor',
|
|
@@ -48955,6 +49820,8 @@ const ORGANIZATION_VIEW_I18N = {
|
|
|
48955
49820
|
inviteCtaTitle: 'Want to add someone?',
|
|
48956
49821
|
inviteCtaHint: 'Invite users to join your organization.',
|
|
48957
49822
|
inviteOpen: 'Invite',
|
|
49823
|
+
importOpen: 'Import',
|
|
49824
|
+
apiKeysOpen: 'API Keys',
|
|
48958
49825
|
viewMemberCta: 'View member',
|
|
48959
49826
|
roleViewer: 'Viewer',
|
|
48960
49827
|
roleEditor: 'Editor',
|
|
@@ -49068,6 +49935,22 @@ class OrganizationViewComponent {
|
|
|
49068
49935
|
this.members = signal([]);
|
|
49069
49936
|
this.membersLoading = signal(false);
|
|
49070
49937
|
this.membersLoadError = signal(null);
|
|
49938
|
+
this.membersErrorState = computed(() => {
|
|
49939
|
+
this.i18n.lang();
|
|
49940
|
+
const err = this.membersLoadError();
|
|
49941
|
+
if (!err)
|
|
49942
|
+
return null;
|
|
49943
|
+
return createErrorStateProps(err, {
|
|
49944
|
+
title: { offline: this.tt('offlineTitle'), error: this.tt('errorTitle') },
|
|
49945
|
+
description: {
|
|
49946
|
+
offline: this.tt('offlineHint'),
|
|
49947
|
+
error: interpretError(err).message,
|
|
49948
|
+
},
|
|
49949
|
+
retryLabel: this.tt('retry'),
|
|
49950
|
+
onRetry: () => this.loadMembers(),
|
|
49951
|
+
retrying: this.membersLoading(),
|
|
49952
|
+
});
|
|
49953
|
+
});
|
|
49071
49954
|
this.membersNextToken = signal(null);
|
|
49072
49955
|
this.loadingMoreMembers = signal(false);
|
|
49073
49956
|
this.showAllMembers = signal(false);
|
|
@@ -49154,6 +50037,22 @@ class OrganizationViewComponent {
|
|
|
49154
50037
|
shape: 'round',
|
|
49155
50038
|
type: 'button',
|
|
49156
50039
|
}));
|
|
50040
|
+
this.openImportButtonProps = computed(() => ({
|
|
50041
|
+
text: this.tt('importOpen'),
|
|
50042
|
+
color: 'dark',
|
|
50043
|
+
fill: 'outline',
|
|
50044
|
+
size: 'default',
|
|
50045
|
+
shape: 'round',
|
|
50046
|
+
type: 'button',
|
|
50047
|
+
}));
|
|
50048
|
+
this.openApiKeysButtonProps = computed(() => ({
|
|
50049
|
+
text: this.tt('apiKeysOpen'),
|
|
50050
|
+
color: 'dark',
|
|
50051
|
+
fill: 'clear',
|
|
50052
|
+
size: 'default',
|
|
50053
|
+
shape: 'round',
|
|
50054
|
+
type: 'button',
|
|
50055
|
+
}));
|
|
49157
50056
|
/** Guarda para detectar el primer disparo del effect (evita doble carga). */
|
|
49158
50057
|
this.lastLoadedOrgId = null;
|
|
49159
50058
|
const ns = this.ns;
|
|
@@ -49254,6 +50153,36 @@ class OrganizationViewComponent {
|
|
|
49254
50153
|
backdropDismiss: true,
|
|
49255
50154
|
});
|
|
49256
50155
|
}
|
|
50156
|
+
onOpenImport() {
|
|
50157
|
+
void this.modalService.open({
|
|
50158
|
+
component: MemberImportModalComponent,
|
|
50159
|
+
componentProps: {
|
|
50160
|
+
orgId: this.activeOrgId(),
|
|
50161
|
+
availableRoles: this.availableRoles().map(r => r.name),
|
|
50162
|
+
onSuccess: () => {
|
|
50163
|
+
this.loadMembers();
|
|
50164
|
+
this.resolvedConfig().onMemberInvited?.();
|
|
50165
|
+
},
|
|
50166
|
+
},
|
|
50167
|
+
breakpoints: {
|
|
50168
|
+
breakpoints: [0, 0.92],
|
|
50169
|
+
initialBreakpoint: 0.92,
|
|
50170
|
+
showHandle: true,
|
|
50171
|
+
},
|
|
50172
|
+
backdropDismiss: true,
|
|
50173
|
+
});
|
|
50174
|
+
}
|
|
50175
|
+
onOpenApiKeys() {
|
|
50176
|
+
void this.modalService.open({
|
|
50177
|
+
component: ApiKeysModalComponent,
|
|
50178
|
+
breakpoints: {
|
|
50179
|
+
breakpoints: [0, 0.92],
|
|
50180
|
+
initialBreakpoint: 0.92,
|
|
50181
|
+
showHandle: true,
|
|
50182
|
+
},
|
|
50183
|
+
backdropDismiss: true,
|
|
50184
|
+
});
|
|
50185
|
+
}
|
|
49257
50186
|
onViewPermissions() {
|
|
49258
50187
|
this.nav.navigateByUrl(this.resolvedConfig().viewPermissionsRoute);
|
|
49259
50188
|
}
|
|
@@ -49335,6 +50264,7 @@ class OrganizationViewComponent {
|
|
|
49335
50264
|
if (!orgId)
|
|
49336
50265
|
return Promise.resolve();
|
|
49337
50266
|
this.membersLoading.set(true);
|
|
50267
|
+
this.membersLoadError.set(null);
|
|
49338
50268
|
this.membersNextToken.set(null);
|
|
49339
50269
|
this.showAllMembers.set(false);
|
|
49340
50270
|
return new Promise(resolve => {
|
|
@@ -49545,6 +50475,8 @@ class OrganizationViewComponent {
|
|
|
49545
50475
|
<div class="section-body">
|
|
49546
50476
|
@if (membersLoading()) {
|
|
49547
50477
|
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
50478
|
+
} @else if (membersErrorState()) {
|
|
50479
|
+
<val-empty-state [props]="membersErrorState()!" />
|
|
49548
50480
|
} @else if (members().length === 0) {
|
|
49549
50481
|
<val-text
|
|
49550
50482
|
[props]="{
|
|
@@ -49637,6 +50569,8 @@ class OrganizationViewComponent {
|
|
|
49637
50569
|
/>
|
|
49638
50570
|
</div>
|
|
49639
50571
|
<val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
|
|
50572
|
+
<val-button [props]="openImportButtonProps()" (click)="onOpenImport()" />
|
|
50573
|
+
<val-button [props]="openApiKeysButtonProps()" (click)="onOpenApiKeys()" />
|
|
49640
50574
|
</div>
|
|
49641
50575
|
</section>
|
|
49642
50576
|
}
|
|
@@ -49745,6 +50679,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
49745
50679
|
ButtonComponent,
|
|
49746
50680
|
MemberCardComponent,
|
|
49747
50681
|
TransferOwnershipModalComponent,
|
|
50682
|
+
MemberImportModalComponent,
|
|
50683
|
+
ApiKeysModalComponent,
|
|
49748
50684
|
], template: `
|
|
49749
50685
|
<div class="page">
|
|
49750
50686
|
<header class="page-header">
|
|
@@ -49823,6 +50759,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
49823
50759
|
<div class="section-body">
|
|
49824
50760
|
@if (membersLoading()) {
|
|
49825
50761
|
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
50762
|
+
} @else if (membersErrorState()) {
|
|
50763
|
+
<val-empty-state [props]="membersErrorState()!" />
|
|
49826
50764
|
} @else if (members().length === 0) {
|
|
49827
50765
|
<val-text
|
|
49828
50766
|
[props]="{
|
|
@@ -49915,6 +50853,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
49915
50853
|
/>
|
|
49916
50854
|
</div>
|
|
49917
50855
|
<val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
|
|
50856
|
+
<val-button [props]="openImportButtonProps()" (click)="onOpenImport()" />
|
|
50857
|
+
<val-button [props]="openApiKeysButtonProps()" (click)="onOpenApiKeys()" />
|
|
49918
50858
|
</div>
|
|
49919
50859
|
</section>
|
|
49920
50860
|
}
|
|
@@ -62662,5 +63602,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
62662
63602
|
* Generated bundle index. Do not edit.
|
|
62663
63603
|
*/
|
|
62664
63604
|
|
|
62665
|
-
export { ACTION_CARD_DEFAULTS, AD_SIZE_MAP, API_TABLE_COLUMN_LABELS, ARTICLE_CARD_DEFAULTS, ARTICLE_SPACING, ARTICLE_STRIP_DEFAULTS, AUTH_CTA_DEFAULTS, AVATAR_UPLOAD_DEFAULTS, AccordionComponent, AccountViewComponent, ActionCardComponent, ActionHeaderComponent, ActionType, AdSlotComponent, AdsLoaderService, AdsService, AlertBoxComponent, AnalyticsErrorHandler, AnalyticsRouterTracker, AnalyticsService, AnimatedTerminalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, 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, PermissionCatalogService, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
63605
|
+
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, ApiKeyService, ApiKeysModalComponent, AppConfigService, AppVersionService, ArticleBuilder, ArticleCardComponent, ArticleComponent, ArticleStripComponent, AttachmentUploaderComponent, AuthBackgroundComponent, AuthCtaComponent, AuthService, AuthStateService, AuthStorageService, AuthSyncService, AvatarComponent, AvatarUploadComponent, BOTTOM_NAV_DEFAULTS, BannerComponent, BaseDefault, BlogPostBuilder, BottomNavComponent, BoxComponent, BreadcrumbComponent, ButtonComponent, ButtonGroupComponent, CALLOUT_LABELS, CHEV_KEYS, CIRCLE_KEYS, COMMON_COUNTRY_CODES, COMMON_CURRENCIES, CONTENT_CARD_DEFAULTS, CORNER_KEYS, CTA_CARD_DEFAULTS, CURRENCY_INFO, CardComponent, CardSection, CardType, CardsCarouselComponent, ChangeEmailModalComponent, ChangePasswordModalComponent, CheckInputComponent, CheckboxRadioInputComponent, ChipGroupComponent, ClearDefault, ClearDefaultBlock, ClearDefaultFull, ClearDefaultRound, ClearDefaultRoundBlock, ClearDefaultRoundFull, CodeDisplayComponent, CommandDisplayComponent, CommentComponent, CommentInputComponent, CommentSectionComponent, CompanyFooterComponent, ComponentStates, ConfirmationDialogService, ContainerComponent, ContentCardComponent, ContentLoaderComponent, ContentReactionComponent, ContentService, ContentTransformer, CookieBannerComponent, CountdownComponent, CreateOrgModalComponent, CtaCardComponent, CurrencyInputComponent, DEFAULT_ADS_CONFIG, DEFAULT_APP_CONFIG_SERVICE_CONFIG, DEFAULT_APP_VERSION_SERVICE_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_BACK_HEADER, DEFAULT_CANCEL_BUTTON, DEFAULT_CHECK_INTERVAL_MS, DEFAULT_CONFIRM_BUTTON, DEFAULT_COUNTDOWN_LABELS, DEFAULT_COUNTDOWN_LABELS_EN, DEFAULT_DEBUG_CONSOLE_CONFIG, DEFAULT_DONATION_CONFIG, DEFAULT_EMPTY_STATE, DEFAULT_EMULATOR_CONFIG, DEFAULT_FEEDBACK_CONFIG, DEFAULT_FEEDBACK_TYPE_OPTIONS, DEFAULT_HOME_HEADER, DEFAULT_INFINITE_LIST_METADATA, DEFAULT_MODAL_CANCEL_BUTTON, DEFAULT_MODAL_CONFIRM_BUTTON, DEFAULT_PAGE_SIZE_OPTIONS, DEFAULT_PLATFORMS, DEFAULT_REFRESHER_METADATA, DEFAULT_SKELETON_CONFIG, DEFAULT_SPLASH_SCREEN_CONFIG, DataTableComponent, DateInputComponent, DateRangeInputComponent, DebugConsoleComponent, DeleteAccountModalComponent, DetailSkeletonComponent, DeviceService, DisplayComponent, DividerComponent, DocsApiTableComponent, DocsBreadcrumbComponent, DocsBuilder, DocsCalloutComponent, DocsCodeExampleComponent, DocsLayoutComponent, DocsNavLinksComponent, DocsNavigationService, DocsPageComponent, DocsSearchComponent, DocsSectionComponent, DocsShellComponent, DocsSidebarComponent, DocsTocComponent, DonationService, DownloadService, EditOrgModalComponent, EmailInputComponent, EmptyStateComponent, ExpandableTextComponent, FEATURES_LIST_DEFAULTS, FUN_MODAL_DEFAULTS, FabComponent, FaqComponent, FeaturesListComponent, FeedbackFormComponent, FeedbackService, FileInputComponent, FirebaseService, FirestoreCollectionFactory, FirestoreService, FontSizeOption, FontSizeService, FooterComponent, FooterLinksComponent, FormComponent, FormSkeletonComponent, FunHeaderComponent, FunModalComponent, GlassComponent, GlowCardComponent, GlowComponent, GridSkeletonComponent, HANDOFF_ROUTE_PARAM, HANDOFF_TOKEN_PARAM, HandoffService, HasPermissionDirective, HeaderComponent, HintComponent, HorizontalScrollComponent, HourInputComponent, HrefComponent, I18nService, IMAGE_DEFAULTS, INFO_CARD_DEFAULTS, INITIAL_AUTH_STATE, INITIAL_MFA_STATE, INVITATION_CARD_DEFAULTS, Icon, IconComponent, IconService, ImageComponent, ImageCropComponent, ImageService, InAppBrowserService, InfiniteListComponent, InfoCardComponent, InfoComponent, InputI18nHelper, InputType, InvitationCardComponent, InviteMemberModalComponent, ItemListComponent, LANG_STORAGE_KEY$1 as LANG_STORAGE_KEY, LEGAL_CONTENT_CONFIG, LOGIN_DEFAULTS, LandingSplitComponent, LandingStepsComponent, LanguageSelectorComponent, LayeredCardComponent, LegalContentService, LegalLinkService, LinkComponent, LinkProcessorService, LinkedProvidersComponent, LinksAccordionComponent, LinksCakeComponent, ListSkeletonComponent, LoadingDirective, LocalStorageService, LocaleService, LoginAttemptModalComponent, LoginComponent, MEDIA_OBJECT_DEFAULTS, MEMBER_CARD_DEFAULTS, METRIC_CARD_DEFAULTS, MODAL_SIZES, MOTIF_KEYS, MOTION, MaintenancePageComponent, MarkdownArticleParserService, MediaObjectComponent, MemberCardComponent, MemberDetailModalComponent, MemberImportModalComponent, MenuComponent, MessagingService, MetaService, MetricCardComponent, MfaModalComponent, ModalService, ModalShellComponent, MultiSelectSearchComponent, NUM_KEYS, NavigationService, NetworkBannerComponent, NetworkStatusService, NewsBuilder, NoContentComponent, NotesBoxComponent, NotificationActionService, NotificationPreferencesViewComponent, NotificationsService, NotificationsViewComponent, NumberFromToComponent, NumberInputComponent, NumberStepperComponent, OAUTH_PROVIDERS_INFO, OAuthCallbackComponent, OAuthService, OrgInfoSheetComponent, OrgService, OrgSwitchService, OrganizationViewComponent, 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, PermissionCatalogService, PermissionsViewComponent, PhoneInputComponent, PillComponent, PinInputComponent, PlainCodeBoxComponent, PopoverSelectorComponent, PreferencesService, PreferencesViewComponent, PresetService, PriceTagComponent, PrimarySolidBlockButton, PrimarySolidBlockHrefButton, PrimarySolidBlockIconButton, PrimarySolidBlockIconHrefButton, PrimarySolidDefaultRoundButton, PrimarySolidDefaultRoundHrefButton, PrimarySolidDefaultRoundIconButton, PrimarySolidDefaultRoundIconHrefButton, PrimarySolidFullButton, PrimarySolidFullHrefButton, PrimarySolidFullIconButton, PrimarySolidFullIconHrefButton, PrimarySolidLargeRoundButton, PrimarySolidLargeRoundHrefButton, PrimarySolidLargeRoundIconButton, PrimarySolidLargeRoundIconHrefButton, PrimarySolidSmallRoundButton, PrimarySolidSmallRoundHrefButton, PrimarySolidSmallRoundIconButton, PrimarySolidSmallRoundIconHrefButton, ProcessLinksPipe, ProfileSkeletonComponent, ProfileViewComponent, ProgressBarComponent, ProgressRingComponent, ProgressStatusComponent, PrompterComponent, QR_PRESETS, QrCodeComponent, QrGeneratorService, QueryBuilder, QuoteBoxComponent, REQUEST_STATUSES, RadioInputComponent, RangeInputComponent, RatingComponent, RefresherComponent, RequestFirestoreService, RequestFormBuilderService, RequestService, RightsFooterComponent, RotatingTextComponent, SEARCH_HEADER_DEFAULTS, SETTINGS_SECTIONS_CATALOG, SHAPE_KEYS, SHARE_PROFILE_MODAL_DEFAULTS, SKELETON_LAYOUT_DEFAULT_ROWS, SKELETON_PRESETS, SOLID_KEYS, STATS_BAR_DEFAULTS, STROKE_KEYS, SearchHeaderComponent, SearchSelectorComponent, SearchbarComponent, SecondarySolidBlockButton, SecondarySolidBlockHrefButton, SecondarySolidBlockIconButton, SecondarySolidBlockIconHrefButton, SecondarySolidDefaultRoundButton, SecondarySolidDefaultRoundHrefButton, SecondarySolidDefaultRoundIconButton, SecondarySolidDefaultRoundIconHrefButton, SecondarySolidFullButton, SecondarySolidFullHrefButton, SecondarySolidFullIconButton, SecondarySolidFullIconHrefButton, SecondarySolidLargeRoundButton, SecondarySolidLargeRoundHrefButton, SecondarySolidLargeRoundIconButton, SecondarySolidLargeRoundIconHrefButton, SecondarySolidSmallRoundButton, SecondarySolidSmallRoundHrefButton, SecondarySolidSmallRoundIconButton, SecondarySolidSmallRoundIconHrefButton, SecurityViewComponent, SegmentControlComponent, SelectSearchComponent, SessionListModalComponent, SessionService, SettingsHubComponent, ShareButtonsComponent, ShareProfileModalComponent, SimpleComponent, SkeletonComponent, SkeletonLayoutComponent, SkeletonService, SolidBlockButton, SolidDefault, SolidDefaultBlock, SolidDefaultButton, SolidDefaultFull, SolidDefaultRound, SolidDefaultRoundBlock, SolidDefaultRoundButton, SolidDefaultRoundFull, SolidFullButton, SolidLargeButton, SolidLargeRoundButton, SolidSmallButton, SolidSmallRoundButton, SplashScreenService, StatsBarComponent, StatsCardComponent, StepperComponent, StorageService, SwipeCarouselComponent, SwitchOrgModalComponent, TRI_KEYS, TabbedContentComponent, TableSkeletonComponent, TabsComponent, Terminal404Component, TestimonialCardComponent, TestimonialCarouselComponent, TextComponent, TextInputComponent, TextareaInputComponent, ThemeOption, ThemeService, TimelineComponent, TitleBlockComponent, TitleComponent, ToastService, ToggleInputComponent, TokenService, ToolbarActionType, ToolbarComponent, TransferOwnershipModalComponent, TranslatePipe, TypedCollection, UPDATE_BANNER_DEFAULT_CONTENT, UPDATE_BANNER_I18N_NAMESPACE, UpdateBannerComponent, UserAvatarComponent, UsernameInputComponent, VALTECH_ADS_CONFIG, VALTECH_APP_CONFIG, VALTECH_APP_VERSION, VALTECH_AUTH_CONFIG, VALTECH_COMPANY_LINKS, VALTECH_CONTENT_CONFIG, VALTECH_DEBUG_CONSOLE, VALTECH_DEFAULT_CONTENT, VALTECH_DONATION_CONFIG, VALTECH_FEEDBACK_CONFIG, VALTECH_FIREBASE_CONFIG, VALTECH_FOOTER_I18N, VALTECH_FOOTER_LOGO, VALTECH_LANGUAGE_SELECTOR, VALTECH_LEGAL_CONFIG, VALTECH_NETWORK_ERROR_KEY, VALTECH_SITE_PATHS, VALTECH_SOCIAL_LINKS, VALTECH_SPLASH_SCREEN, VALTECH_WEB_BASE_URLS, VERSION, ValtechErrorService, WizardComponent, WizardFooterComponent, applyDefaultValueToControl, authGuard, authInterceptor, authPasswordValidator, beautifyLegalArticle, blogPost, buildCompanyFooterProps, buildFooterLinks, buildLegalLinkResolver, buildPath, buildSettingsCards, collections, connectPageRefresh, createErrorStateProps, createFirebaseConfig, createGlowCardProps, createInitialPaginationState, createNumberFromToField, createRefreshableStream, createTitleProps, docs, errorLoggingInterceptor, extractPathParams, generatePatternTiles, generateRandomTile, getAppInfo, getAppVersion, getCollectionPath, getDocumentId, getTimeOfDayKey, goToTop, guestGuard, hasEmulators, interpretError, isAtEnd, isCollectionPath, isDocumentPath, isEmulatorMode, isValidPath, joinPath, maxLength, mulberry32, news, parseMarkdownArticle, permissionGuard, permissionGuardFromRoute, provideLegalContent, provideSplashScreen, provideValtechAccountRoutes, provideValtechAds, provideValtechAppConfig, provideValtechAppVersion, provideValtechAuth, provideValtechAuthInterceptor, provideValtechContent, provideValtechDebugConsole, provideValtechDonations, provideValtechErrorHandling, provideValtechFeedback, provideValtechFirebase, provideValtechI18n, provideValtechLegal, provideValtechNotificationPreferencesRoutes, provideValtechNotificationsRoutes, provideValtechOrganizationRoutes, provideValtechPermissionsRoutes, provideValtechPreferencesRoutes, provideValtechPresets, provideValtechProfileRoutes, provideValtechSecurityRoutes, provideValtechSettingsRoutes, provideValtechSite, provideValtechSkeleton, query, renderPatternSvgInner, replaceSpecialChars, resolveColor$1 as resolveColor, resolveInputDefaultValue, resolveWebBaseUrl, roleGuard, storagePaths, superAdminGuard, toArticle };
|
|
62666
63606
|
//# sourceMappingURL=valtech-components.mjs.map
|