valtech-components 2.0.998 → 2.0.999
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/organization-view/organization-view.component.mjs +1 -76
- package/esm2022/lib/components/organisms/organization-view/organization-view.i18n.mjs +1 -5
- package/esm2022/lib/components/organisms/permissions-view/permissions-view.component.mjs +14 -9
- package/esm2022/lib/components/organisms/permissions-view/permissions-view.i18n.mjs +3 -1
- package/esm2022/lib/services/auth/auth.service.mjs +1 -14
- package/esm2022/lib/services/auth/types.mjs +1 -1
- package/esm2022/lib/services/org/org.service.mjs +1 -8
- package/esm2022/lib/services/org/permission-catalog.service.mjs +1 -1
- package/esm2022/lib/services/org/types.mjs +1 -1
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +1 -4
- package/fesm2022/valtech-components.mjs +57 -990
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/organization-view/organization-view.component.d.ts +0 -5
- package/lib/services/auth/auth.service.d.ts +1 -7
- package/lib/services/auth/types.d.ts +0 -23
- package/lib/services/org/org.service.d.ts +1 -6
- package/lib/services/org/permission-catalog.service.d.ts +1 -1
- package/lib/services/org/types.d.ts +0 -30
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +1 -5
- package/esm2022/lib/components/organisms/api-keys-modal/api-keys-modal.component.mjs +0 -385
- package/esm2022/lib/components/organisms/api-keys-modal/api-keys-modal.i18n.mjs +0 -63
- package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.component.mjs +0 -313
- package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.i18n.mjs +0 -63
- package/esm2022/lib/services/apikeys/api-keys.service.mjs +0 -46
- package/esm2022/lib/services/apikeys/types.mjs +0 -7
- package/lib/components/organisms/api-keys-modal/api-keys-modal.component.d.ts +0 -44
- package/lib/components/organisms/api-keys-modal/api-keys-modal.i18n.d.ts +0 -6
- package/lib/components/organisms/member-import-modal/member-import-modal.component.d.ts +0 -47
- package/lib/components/organisms/member-import-modal/member-import-modal.i18n.d.ts +0 -6
- package/lib/services/apikeys/api-keys.service.d.ts +0 -25
- package/lib/services/apikeys/types.d.ts +0 -46
|
@@ -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.999';
|
|
58
58
|
|
|
59
59
|
// Control de estado de refresco (singleton a nivel de módulo)
|
|
60
60
|
let isRefreshing = false;
|
|
@@ -8658,19 +8658,6 @@ 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
|
-
}
|
|
8674
8661
|
/**
|
|
8675
8662
|
* Cambia la contraseña del usuario autenticado.
|
|
8676
8663
|
* Requiere la contraseña actual para verificación.
|
|
@@ -41750,7 +41737,7 @@ const PROFILE_VIEW_I18N = {
|
|
|
41750
41737
|
const HANDLE_PATTERN = /^[a-z_][a-z0-9_]*$/;
|
|
41751
41738
|
const HANDLE_MIN = 3;
|
|
41752
41739
|
const HANDLE_MAX = 20;
|
|
41753
|
-
const DEFAULT_NAMESPACE$
|
|
41740
|
+
const DEFAULT_NAMESPACE$f = 'Settings.Profile';
|
|
41754
41741
|
/**
|
|
41755
41742
|
* `val-profile-view` — vista Perfil full-feature autocontenida (organism).
|
|
41756
41743
|
*
|
|
@@ -41800,7 +41787,7 @@ class ProfileViewComponent {
|
|
|
41800
41787
|
showPhone: merged.showPhone ?? true,
|
|
41801
41788
|
showShareCta: merged.showShareCta ?? true,
|
|
41802
41789
|
profileBaseUrl: merged.profileBaseUrl ?? '',
|
|
41803
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
41790
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$f,
|
|
41804
41791
|
onSaved: merged.onSaved,
|
|
41805
41792
|
onAvatarUploaded: merged.onAvatarUploaded,
|
|
41806
41793
|
};
|
|
@@ -42716,7 +42703,7 @@ const PREFERENCES_VIEW_I18N = {
|
|
|
42716
42703
|
},
|
|
42717
42704
|
};
|
|
42718
42705
|
|
|
42719
|
-
const DEFAULT_NAMESPACE$
|
|
42706
|
+
const DEFAULT_NAMESPACE$e = 'Settings.General';
|
|
42720
42707
|
const DEFAULT_LANGUAGES = ['es', 'en'];
|
|
42721
42708
|
/**
|
|
42722
42709
|
* `val-preferences-view` — vista de preferencias de UI cross-app (tema +
|
|
@@ -42753,7 +42740,7 @@ class PreferencesViewComponent {
|
|
|
42753
42740
|
showLanguage: merged.showLanguage ?? true,
|
|
42754
42741
|
showFontSize: merged.showFontSize ?? true,
|
|
42755
42742
|
supportedLanguages: merged.supportedLanguages ?? DEFAULT_LANGUAGES,
|
|
42756
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
42743
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$e,
|
|
42757
42744
|
onThemeChanged: merged.onThemeChanged,
|
|
42758
42745
|
onLanguageChanged: merged.onLanguageChanged,
|
|
42759
42746
|
onFontSizeChanged: merged.onFontSizeChanged,
|
|
@@ -44509,7 +44496,7 @@ const SECURITY_VIEW_I18N = {
|
|
|
44509
44496
|
};
|
|
44510
44497
|
|
|
44511
44498
|
addIcons({ laptopOutline, phonePortraitOutline });
|
|
44512
|
-
const DEFAULT_NAMESPACE$
|
|
44499
|
+
const DEFAULT_NAMESPACE$d = 'Settings.Security';
|
|
44513
44500
|
/**
|
|
44514
44501
|
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
44515
44502
|
*
|
|
@@ -44558,7 +44545,7 @@ class SecurityViewComponent {
|
|
|
44558
44545
|
showChangeEmail: merged.showChangeEmail ?? true,
|
|
44559
44546
|
showMfa: merged.showMfa ?? true,
|
|
44560
44547
|
showPolicies: merged.showPolicies ?? true,
|
|
44561
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
44548
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$d,
|
|
44562
44549
|
handleDeepLinks: merged.handleDeepLinks ?? true,
|
|
44563
44550
|
homeRoute: merged.homeRoute ?? '/app/home',
|
|
44564
44551
|
onMfaCompleted: merged.onMfaCompleted,
|
|
@@ -45360,13 +45347,6 @@ class OrgService {
|
|
|
45360
45347
|
inviteUser(orgId, req) {
|
|
45361
45348
|
return this.http.post(`${this.baseUrl}/${orgId}/invite`, req);
|
|
45362
45349
|
}
|
|
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
|
-
}
|
|
45370
45350
|
leaveOrg(orgId) {
|
|
45371
45351
|
return this.http.post(`${this.baseUrl}/${orgId}/leave`, {});
|
|
45372
45352
|
}
|
|
@@ -45471,7 +45451,7 @@ const CREATE_ORG_MODAL_I18N = {
|
|
|
45471
45451
|
},
|
|
45472
45452
|
};
|
|
45473
45453
|
|
|
45474
|
-
const DEFAULT_NAMESPACE$
|
|
45454
|
+
const DEFAULT_NAMESPACE$c = 'CreateOrgModal';
|
|
45475
45455
|
/**
|
|
45476
45456
|
* `val-create-org-modal` — modal de creación de organización (organism
|
|
45477
45457
|
* compartido). Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por
|
|
@@ -45497,10 +45477,10 @@ class CreateOrgModalComponent {
|
|
|
45497
45477
|
this.toast = inject(ToastService);
|
|
45498
45478
|
this.errors = inject(ValtechErrorService);
|
|
45499
45479
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45500
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45480
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$c;
|
|
45501
45481
|
this._busy = signal(false);
|
|
45502
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45503
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45482
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$c)) {
|
|
45483
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$c, CREATE_ORG_MODAL_I18N);
|
|
45504
45484
|
}
|
|
45505
45485
|
this.formMeta = signal(this.buildFormMeta());
|
|
45506
45486
|
effect(() => {
|
|
@@ -45736,7 +45716,7 @@ const DELETE_ACCOUNT_MODAL_I18N = {
|
|
|
45736
45716
|
},
|
|
45737
45717
|
};
|
|
45738
45718
|
|
|
45739
|
-
const DEFAULT_NAMESPACE$
|
|
45719
|
+
const DEFAULT_NAMESPACE$b = 'Settings.DeleteAccount';
|
|
45740
45720
|
/**
|
|
45741
45721
|
* `val-delete-account-modal` — modal de eliminación de cuenta (organism,
|
|
45742
45722
|
* cuenta-específico). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -45762,7 +45742,7 @@ class DeleteAccountModalComponent {
|
|
|
45762
45742
|
this.i18n = inject(I18nService);
|
|
45763
45743
|
this.toast = inject(ToastService);
|
|
45764
45744
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
45765
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
45745
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$b;
|
|
45766
45746
|
this.hasPassword = signal(null);
|
|
45767
45747
|
this.codeSent = signal(false);
|
|
45768
45748
|
this.formState = signal(ComponentStates.ENABLED);
|
|
@@ -45829,8 +45809,8 @@ class DeleteAccountModalComponent {
|
|
|
45829
45809
|
],
|
|
45830
45810
|
actions: this.submitBtn('delete-code-submit', 'confirmCta'),
|
|
45831
45811
|
}));
|
|
45832
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
45833
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
45812
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$b)) {
|
|
45813
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$b, DELETE_ACCOUNT_MODAL_I18N);
|
|
45834
45814
|
}
|
|
45835
45815
|
}
|
|
45836
45816
|
ngOnInit() {
|
|
@@ -46031,7 +46011,7 @@ const ORG_INFO_SHEET_I18N = {
|
|
|
46031
46011
|
},
|
|
46032
46012
|
};
|
|
46033
46013
|
|
|
46034
|
-
const DEFAULT_NAMESPACE$
|
|
46014
|
+
const DEFAULT_NAMESPACE$a = 'OrgInfoSheet';
|
|
46035
46015
|
/**
|
|
46036
46016
|
* `val-org-info-sheet` — sheet informativo "¿Qué son las organizaciones?".
|
|
46037
46017
|
* Extraído del `OrgInfoSheetComponent` inline de `AccountPage` bajo el proceso de
|
|
@@ -46076,15 +46056,15 @@ class OrgInfoSheetComponent {
|
|
|
46076
46056
|
text: this.closeProps.text || this.resolvedCloseLabel(),
|
|
46077
46057
|
}));
|
|
46078
46058
|
addIcons({ peopleOutline, swapHorizontalOutline, mailOutline });
|
|
46079
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46080
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46059
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$a)) {
|
|
46060
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$a, ORG_INFO_SHEET_I18N);
|
|
46081
46061
|
}
|
|
46082
46062
|
}
|
|
46083
46063
|
dismiss() {
|
|
46084
46064
|
this._modalRef?.dismiss(null, 'cancel');
|
|
46085
46065
|
}
|
|
46086
46066
|
tt(key) {
|
|
46087
|
-
return this.i18n.t(key, DEFAULT_NAMESPACE$
|
|
46067
|
+
return this.i18n.t(key, DEFAULT_NAMESPACE$a);
|
|
46088
46068
|
}
|
|
46089
46069
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OrgInfoSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46090
46070
|
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: `
|
|
@@ -46251,7 +46231,7 @@ const SWITCH_ORG_MODAL_I18N = {
|
|
|
46251
46231
|
},
|
|
46252
46232
|
};
|
|
46253
46233
|
|
|
46254
|
-
const DEFAULT_NAMESPACE$
|
|
46234
|
+
const DEFAULT_NAMESPACE$9 = 'Settings.SwitchOrg';
|
|
46255
46235
|
addIcons({ businessOutline, checkmarkCircleOutline });
|
|
46256
46236
|
/**
|
|
46257
46237
|
* `val-switch-org-modal` — modal de cambio de organización activa (organism
|
|
@@ -46277,7 +46257,7 @@ class SwitchOrgModalComponent {
|
|
|
46277
46257
|
this.orgSwitch = inject(OrgSwitchService);
|
|
46278
46258
|
this.errors = inject(ValtechErrorService);
|
|
46279
46259
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
46280
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
46260
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$9;
|
|
46281
46261
|
this.orgs = signal([]);
|
|
46282
46262
|
this.loading = signal(false);
|
|
46283
46263
|
this.query = signal('');
|
|
@@ -46293,8 +46273,8 @@ class SwitchOrgModalComponent {
|
|
|
46293
46273
|
return list;
|
|
46294
46274
|
return list.filter(o => o.name.toLowerCase().includes(q));
|
|
46295
46275
|
});
|
|
46296
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
46297
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
46276
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$9)) {
|
|
46277
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$9, SWITCH_ORG_MODAL_I18N);
|
|
46298
46278
|
}
|
|
46299
46279
|
this.loadOrgs();
|
|
46300
46280
|
}
|
|
@@ -46612,7 +46592,7 @@ const ACCOUNT_VIEW_I18N = {
|
|
|
46612
46592
|
};
|
|
46613
46593
|
|
|
46614
46594
|
addIcons({ peopleOutline, businessOutline, chevronForwardOutline, swapHorizontalOutline, mailOutline });
|
|
46615
|
-
const DEFAULT_NAMESPACE$
|
|
46595
|
+
const DEFAULT_NAMESPACE$8 = 'Settings.Account';
|
|
46616
46596
|
const DEFAULT_MANAGE_ORG_ROUTE = '/app/settings/organization';
|
|
46617
46597
|
/**
|
|
46618
46598
|
* `val-account-view` — vista Cuenta full-feature autocontenida (organism).
|
|
@@ -46653,7 +46633,7 @@ class AccountViewComponent {
|
|
|
46653
46633
|
showNewOrgCta: merged.showNewOrgCta ?? true,
|
|
46654
46634
|
showLogout: merged.showLogout ?? true,
|
|
46655
46635
|
showDeleteAccount: merged.showDeleteAccount ?? true,
|
|
46656
|
-
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$
|
|
46636
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE$8,
|
|
46657
46637
|
manageOrgRoute: merged.manageOrgRoute ?? DEFAULT_MANAGE_ORG_ROUTE,
|
|
46658
46638
|
onOrgSwitched: merged.onOrgSwitched,
|
|
46659
46639
|
onOrgCreated: merged.onOrgCreated,
|
|
@@ -47378,7 +47358,7 @@ const EDIT_ORG_MODAL_I18N = {
|
|
|
47378
47358
|
},
|
|
47379
47359
|
};
|
|
47380
47360
|
|
|
47381
|
-
const DEFAULT_NAMESPACE$
|
|
47361
|
+
const DEFAULT_NAMESPACE$7 = 'EditOrgModal';
|
|
47382
47362
|
/**
|
|
47383
47363
|
* `val-edit-org-modal` — modal de edición de organización (nombre + descripción).
|
|
47384
47364
|
* Promovido desde `showcase` bajo el proceso de ADR-021. Reusado por la vista de
|
|
@@ -47405,10 +47385,10 @@ class EditOrgModalComponent {
|
|
|
47405
47385
|
/** Organización a editar (pasada por `componentProps`). */
|
|
47406
47386
|
this.org = null;
|
|
47407
47387
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47408
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
47388
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$7;
|
|
47409
47389
|
this.saving = signal(false);
|
|
47410
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
47411
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
47390
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$7)) {
|
|
47391
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$7, EDIT_ORG_MODAL_I18N);
|
|
47412
47392
|
}
|
|
47413
47393
|
this.formMeta = signal(this.buildFormMeta());
|
|
47414
47394
|
effect(() => {
|
|
@@ -47646,7 +47626,7 @@ const INVITE_MEMBER_MODAL_I18N = {
|
|
|
47646
47626
|
},
|
|
47647
47627
|
};
|
|
47648
47628
|
|
|
47649
|
-
const DEFAULT_NAMESPACE$
|
|
47629
|
+
const DEFAULT_NAMESPACE$6 = 'InviteModal';
|
|
47650
47630
|
addIcons({ personOutline, mailOutline, closeOutline, checkmarkCircleOutline });
|
|
47651
47631
|
/**
|
|
47652
47632
|
* `val-invite-member-modal` — invitación de miembros a una organización.
|
|
@@ -47677,7 +47657,7 @@ class InviteMemberModalComponent {
|
|
|
47677
47657
|
/** Ids de miembros ya existentes (excluidos de los resultados). */
|
|
47678
47658
|
this.existingMemberIds = [];
|
|
47679
47659
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
47680
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
47660
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$6;
|
|
47681
47661
|
this.query = signal('');
|
|
47682
47662
|
this.searching = signal(false);
|
|
47683
47663
|
this.searchResults = signal([]);
|
|
@@ -47724,8 +47704,8 @@ class InviteMemberModalComponent {
|
|
|
47724
47704
|
state: this.sending() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
47725
47705
|
}));
|
|
47726
47706
|
this.searchSubject = new Subject();
|
|
47727
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
47728
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
47707
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$6)) {
|
|
47708
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$6, INVITE_MEMBER_MODAL_I18N);
|
|
47729
47709
|
}
|
|
47730
47710
|
this.loadRoles();
|
|
47731
47711
|
this.roleSub = this.roleControl.valueChanges.subscribe(v => {
|
|
@@ -48214,7 +48194,7 @@ const MEMBER_DETAIL_MODAL_I18N = {
|
|
|
48214
48194
|
},
|
|
48215
48195
|
};
|
|
48216
48196
|
|
|
48217
|
-
const DEFAULT_NAMESPACE$
|
|
48197
|
+
const DEFAULT_NAMESPACE$5 = 'Settings.MemberDetail';
|
|
48218
48198
|
/**
|
|
48219
48199
|
* `val-member-detail-modal` — detalle de miembro de organización: perfil, rol y
|
|
48220
48200
|
* permisos. Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
@@ -48251,7 +48231,7 @@ class MemberDetailModalComponent {
|
|
|
48251
48231
|
{ id: 'admin', name: 'admin' },
|
|
48252
48232
|
];
|
|
48253
48233
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48254
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
48234
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$5;
|
|
48255
48235
|
this.working = signal(false);
|
|
48256
48236
|
this.currentRole = signal('');
|
|
48257
48237
|
this.roleControl = new FormControl('');
|
|
@@ -48291,8 +48271,8 @@ class MemberDetailModalComponent {
|
|
|
48291
48271
|
type: 'button',
|
|
48292
48272
|
state: this.working() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
48293
48273
|
}));
|
|
48294
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
48295
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
48274
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$5)) {
|
|
48275
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$5, MEMBER_DETAIL_MODAL_I18N);
|
|
48296
48276
|
}
|
|
48297
48277
|
}
|
|
48298
48278
|
ngOnInit() {
|
|
@@ -48629,7 +48609,7 @@ const TRANSFER_OWNERSHIP_MODAL_I18N = {
|
|
|
48629
48609
|
},
|
|
48630
48610
|
};
|
|
48631
48611
|
|
|
48632
|
-
const DEFAULT_NAMESPACE$
|
|
48612
|
+
const DEFAULT_NAMESPACE$4 = 'Settings.TransferModal';
|
|
48633
48613
|
/**
|
|
48634
48614
|
* `val-transfer-ownership-modal` — selector de miembro para transferir la
|
|
48635
48615
|
* propiedad de la organización. Promovido desde `showcase` bajo el proceso de
|
|
@@ -48653,7 +48633,7 @@ class TransferOwnershipModalComponent {
|
|
|
48653
48633
|
/** Lista de miembros transferibles (todos excepto el owner actual). */
|
|
48654
48634
|
this.members = [];
|
|
48655
48635
|
/** Namespace i18n con que la vista resuelve sus textos. */
|
|
48656
|
-
this.i18nNamespace = DEFAULT_NAMESPACE$
|
|
48636
|
+
this.i18nNamespace = DEFAULT_NAMESPACE$4;
|
|
48657
48637
|
this.query = signal('');
|
|
48658
48638
|
this.selectedId = signal('');
|
|
48659
48639
|
this.filtered = computed(() => {
|
|
@@ -48665,8 +48645,8 @@ class TransferOwnershipModalComponent {
|
|
|
48665
48645
|
m.userId.toLowerCase().includes(q));
|
|
48666
48646
|
});
|
|
48667
48647
|
this.noResultsLabel = computed(() => `${this.t('noResults')} "${this.query()}"`);
|
|
48668
|
-
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$
|
|
48669
|
-
this.i18n.registerContent(DEFAULT_NAMESPACE$
|
|
48648
|
+
if (!this.i18n.hasNamespace(DEFAULT_NAMESPACE$4)) {
|
|
48649
|
+
this.i18n.registerContent(DEFAULT_NAMESPACE$4, TRANSFER_OWNERSHIP_MODAL_I18N);
|
|
48670
48650
|
}
|
|
48671
48651
|
}
|
|
48672
48652
|
ngOnInit() {
|
|
@@ -48851,849 +48831,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
48851
48831
|
type: Input
|
|
48852
48832
|
}] } });
|
|
48853
48833
|
|
|
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
|
-
|
|
49697
48834
|
/**
|
|
49698
48835
|
* Defaults i18n (es/en) embebidos en `val-organization-view`. Auto-registrados en
|
|
49699
48836
|
* el constructor del componente si el consumer no proveyó el namespace
|
|
@@ -49749,8 +48886,6 @@ const ORGANIZATION_VIEW_I18N = {
|
|
|
49749
48886
|
inviteCtaTitle: '¿Deseas agregar a alguien?',
|
|
49750
48887
|
inviteCtaHint: 'Invita a usuarios a unirse a tu organización.',
|
|
49751
48888
|
inviteOpen: 'Invitar',
|
|
49752
|
-
importOpen: 'Importar',
|
|
49753
|
-
apiKeysOpen: 'API Keys',
|
|
49754
48889
|
viewMemberCta: 'Ver miembro',
|
|
49755
48890
|
roleViewer: 'Visor',
|
|
49756
48891
|
roleEditor: 'Editor',
|
|
@@ -49820,8 +48955,6 @@ const ORGANIZATION_VIEW_I18N = {
|
|
|
49820
48955
|
inviteCtaTitle: 'Want to add someone?',
|
|
49821
48956
|
inviteCtaHint: 'Invite users to join your organization.',
|
|
49822
48957
|
inviteOpen: 'Invite',
|
|
49823
|
-
importOpen: 'Import',
|
|
49824
|
-
apiKeysOpen: 'API Keys',
|
|
49825
48958
|
viewMemberCta: 'View member',
|
|
49826
48959
|
roleViewer: 'Viewer',
|
|
49827
48960
|
roleEditor: 'Editor',
|
|
@@ -49935,22 +49068,6 @@ class OrganizationViewComponent {
|
|
|
49935
49068
|
this.members = signal([]);
|
|
49936
49069
|
this.membersLoading = signal(false);
|
|
49937
49070
|
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
|
-
});
|
|
49954
49071
|
this.membersNextToken = signal(null);
|
|
49955
49072
|
this.loadingMoreMembers = signal(false);
|
|
49956
49073
|
this.showAllMembers = signal(false);
|
|
@@ -50037,22 +49154,6 @@ class OrganizationViewComponent {
|
|
|
50037
49154
|
shape: 'round',
|
|
50038
49155
|
type: 'button',
|
|
50039
49156
|
}));
|
|
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
|
-
}));
|
|
50056
49157
|
/** Guarda para detectar el primer disparo del effect (evita doble carga). */
|
|
50057
49158
|
this.lastLoadedOrgId = null;
|
|
50058
49159
|
const ns = this.ns;
|
|
@@ -50153,36 +49254,6 @@ class OrganizationViewComponent {
|
|
|
50153
49254
|
backdropDismiss: true,
|
|
50154
49255
|
});
|
|
50155
49256
|
}
|
|
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
|
-
}
|
|
50186
49257
|
onViewPermissions() {
|
|
50187
49258
|
this.nav.navigateByUrl(this.resolvedConfig().viewPermissionsRoute);
|
|
50188
49259
|
}
|
|
@@ -50264,7 +49335,6 @@ class OrganizationViewComponent {
|
|
|
50264
49335
|
if (!orgId)
|
|
50265
49336
|
return Promise.resolve();
|
|
50266
49337
|
this.membersLoading.set(true);
|
|
50267
|
-
this.membersLoadError.set(null);
|
|
50268
49338
|
this.membersNextToken.set(null);
|
|
50269
49339
|
this.showAllMembers.set(false);
|
|
50270
49340
|
return new Promise(resolve => {
|
|
@@ -50475,8 +49545,6 @@ class OrganizationViewComponent {
|
|
|
50475
49545
|
<div class="section-body">
|
|
50476
49546
|
@if (membersLoading()) {
|
|
50477
49547
|
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
50478
|
-
} @else if (membersErrorState()) {
|
|
50479
|
-
<val-empty-state [props]="membersErrorState()!" />
|
|
50480
49548
|
} @else if (members().length === 0) {
|
|
50481
49549
|
<val-text
|
|
50482
49550
|
[props]="{
|
|
@@ -50569,8 +49637,6 @@ class OrganizationViewComponent {
|
|
|
50569
49637
|
/>
|
|
50570
49638
|
</div>
|
|
50571
49639
|
<val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
|
|
50572
|
-
<val-button [props]="openImportButtonProps()" (click)="onOpenImport()" />
|
|
50573
|
-
<val-button [props]="openApiKeysButtonProps()" (click)="onOpenApiKeys()" />
|
|
50574
49640
|
</div>
|
|
50575
49641
|
</section>
|
|
50576
49642
|
}
|
|
@@ -50679,8 +49745,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
50679
49745
|
ButtonComponent,
|
|
50680
49746
|
MemberCardComponent,
|
|
50681
49747
|
TransferOwnershipModalComponent,
|
|
50682
|
-
MemberImportModalComponent,
|
|
50683
|
-
ApiKeysModalComponent,
|
|
50684
49748
|
], template: `
|
|
50685
49749
|
<div class="page">
|
|
50686
49750
|
<header class="page-header">
|
|
@@ -50759,8 +49823,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
50759
49823
|
<div class="section-body">
|
|
50760
49824
|
@if (membersLoading()) {
|
|
50761
49825
|
<val-skeleton-layout [props]="{ preset: 'list', rows: 3 }" />
|
|
50762
|
-
} @else if (membersErrorState()) {
|
|
50763
|
-
<val-empty-state [props]="membersErrorState()!" />
|
|
50764
49826
|
} @else if (members().length === 0) {
|
|
50765
49827
|
<val-text
|
|
50766
49828
|
[props]="{
|
|
@@ -50853,8 +49915,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
50853
49915
|
/>
|
|
50854
49916
|
</div>
|
|
50855
49917
|
<val-button [props]="openInviteButtonProps()" (click)="onOpenInvite()" />
|
|
50856
|
-
<val-button [props]="openImportButtonProps()" (click)="onOpenImport()" />
|
|
50857
|
-
<val-button [props]="openApiKeysButtonProps()" (click)="onOpenApiKeys()" />
|
|
50858
49918
|
</div>
|
|
50859
49919
|
</section>
|
|
50860
49920
|
}
|
|
@@ -52779,6 +51839,7 @@ const PERMISSIONS_VIEW_I18N = {
|
|
|
52779
51839
|
noPermissions: 'Sin permisos asignados.',
|
|
52780
51840
|
// Grupos de alcance
|
|
52781
51841
|
groupApp: 'Permisos de la app',
|
|
51842
|
+
groupOrg: 'Permisos de la organización',
|
|
52782
51843
|
groupPlatform: 'Permisos de plataforma',
|
|
52783
51844
|
groupOther: 'Otras apps',
|
|
52784
51845
|
// Roles del sistema
|
|
@@ -52834,6 +51895,7 @@ const PERMISSIONS_VIEW_I18N = {
|
|
|
52834
51895
|
noCustomRoles: 'This organization has no custom roles.',
|
|
52835
51896
|
noPermissions: 'No permissions assigned.',
|
|
52836
51897
|
groupApp: 'App permissions',
|
|
51898
|
+
groupOrg: 'Organization permissions',
|
|
52837
51899
|
groupPlatform: 'Platform permissions',
|
|
52838
51900
|
groupOther: 'Other apps',
|
|
52839
51901
|
roleViewer: 'Viewer',
|
|
@@ -52975,12 +52037,17 @@ class PermissionsViewComponent {
|
|
|
52975
52037
|
}
|
|
52976
52038
|
buildRoleView(role, byResource, currentAppId) {
|
|
52977
52039
|
const appPerms = [];
|
|
52978
|
-
const
|
|
52040
|
+
const orgPerms = [];
|
|
52979
52041
|
const otherByApp = new Map();
|
|
52980
52042
|
for (const perm of role.permissions) {
|
|
52981
52043
|
const [resource, action] = perm.split(':');
|
|
52982
|
-
const label = this.permLabel(resource, action);
|
|
52983
52044
|
const entry = byResource.get(resource);
|
|
52045
|
+
// internal (operación de plataforma) NUNCA se muestra a nivel de producto
|
|
52046
|
+
// — defensa en profundidad junto al filtro del backend (ADR-024).
|
|
52047
|
+
if (entry?.scope === 'internal') {
|
|
52048
|
+
continue;
|
|
52049
|
+
}
|
|
52050
|
+
const label = this.permLabel(resource, action);
|
|
52984
52051
|
if (entry?.scope === 'app') {
|
|
52985
52052
|
if (entry.appId === currentAppId) {
|
|
52986
52053
|
appPerms.push(label);
|
|
@@ -52993,19 +52060,19 @@ class PermissionsViewComponent {
|
|
|
52993
52060
|
}
|
|
52994
52061
|
}
|
|
52995
52062
|
else {
|
|
52996
|
-
//
|
|
52997
|
-
|
|
52063
|
+
// org o desconocido → gestión de la organización del cliente
|
|
52064
|
+
orgPerms.push(label);
|
|
52998
52065
|
}
|
|
52999
52066
|
}
|
|
53000
52067
|
const groups = [];
|
|
53001
52068
|
if (appPerms.length) {
|
|
53002
52069
|
groups.push({ key: 'app', label: this.tt('groupApp'), perms: appPerms });
|
|
53003
52070
|
}
|
|
53004
|
-
if (
|
|
52071
|
+
if (orgPerms.length) {
|
|
53005
52072
|
groups.push({
|
|
53006
|
-
key: '
|
|
53007
|
-
label: this.tt('
|
|
53008
|
-
perms:
|
|
52073
|
+
key: 'org',
|
|
52074
|
+
label: this.tt('groupOrg'),
|
|
52075
|
+
perms: orgPerms,
|
|
53009
52076
|
});
|
|
53010
52077
|
}
|
|
53011
52078
|
for (const [appId, perms] of otherByApp) {
|
|
@@ -63602,5 +62669,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
63602
62669
|
* Generated bundle index. Do not edit.
|
|
63603
62670
|
*/
|
|
63604
62671
|
|
|
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 };
|
|
62672
|
+
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 };
|
|
63606
62673
|
//# sourceMappingURL=valtech-components.mjs.map
|