valtech-components 2.0.996 → 2.0.997

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.
Files changed (50) hide show
  1. package/esm2022/lib/components/organisms/notification-preferences-view/notification-preferences-view.component.mjs +667 -0
  2. package/esm2022/lib/components/organisms/notification-preferences-view/notification-preferences-view.i18n.mjs +71 -0
  3. package/esm2022/lib/components/organisms/notification-preferences-view/notification-preferences.routes.mjs +31 -0
  4. package/esm2022/lib/components/organisms/notification-preferences-view/types.mjs +2 -0
  5. package/esm2022/lib/components/organisms/organization-view/organization-view.component.mjs +1 -76
  6. package/esm2022/lib/components/organisms/organization-view/organization-view.i18n.mjs +1 -5
  7. package/esm2022/lib/components/organisms/permissions-view/permissions-view.component.mjs +511 -0
  8. package/esm2022/lib/components/organisms/permissions-view/permissions-view.i18n.mjs +116 -0
  9. package/esm2022/lib/components/organisms/permissions-view/permissions.routes.mjs +29 -0
  10. package/esm2022/lib/components/organisms/permissions-view/types.mjs +2 -0
  11. package/esm2022/lib/components/organisms/settings-hub/settings.routes.mjs +12 -1
  12. package/esm2022/lib/services/auth/auth.service.mjs +1 -14
  13. package/esm2022/lib/services/auth/types.mjs +1 -1
  14. package/esm2022/lib/services/org/org.service.mjs +1 -8
  15. package/esm2022/lib/services/org/permission-catalog.service.mjs +33 -0
  16. package/esm2022/lib/services/org/types.mjs +1 -1
  17. package/esm2022/lib/version.mjs +2 -2
  18. package/esm2022/public-api.mjs +8 -4
  19. package/fesm2022/valtech-components.mjs +1484 -1003
  20. package/fesm2022/valtech-components.mjs.map +1 -1
  21. package/lib/components/organisms/notification-preferences-view/notification-preferences-view.component.d.ts +146 -0
  22. package/lib/components/organisms/notification-preferences-view/notification-preferences-view.i18n.d.ts +11 -0
  23. package/lib/components/organisms/notification-preferences-view/notification-preferences.routes.d.ts +26 -0
  24. package/lib/components/organisms/notification-preferences-view/types.d.ts +36 -0
  25. package/lib/components/organisms/organization-view/organization-view.component.d.ts +0 -5
  26. package/lib/components/organisms/permissions-view/permissions-view.component.d.ts +71 -0
  27. package/lib/components/organisms/permissions-view/permissions-view.i18n.d.ts +9 -0
  28. package/lib/components/organisms/permissions-view/permissions.routes.d.ts +24 -0
  29. package/lib/components/organisms/permissions-view/types.d.ts +26 -0
  30. package/lib/components/organisms/settings-hub/settings.routes.d.ts +15 -0
  31. package/lib/services/auth/auth.service.d.ts +1 -7
  32. package/lib/services/auth/types.d.ts +0 -23
  33. package/lib/services/org/org.service.d.ts +1 -6
  34. package/lib/services/org/permission-catalog.service.d.ts +34 -0
  35. package/lib/services/org/types.d.ts +0 -30
  36. package/lib/version.d.ts +1 -1
  37. package/package.json +1 -1
  38. package/public-api.d.ts +8 -5
  39. package/esm2022/lib/components/organisms/api-keys-modal/api-keys-modal.component.mjs +0 -385
  40. package/esm2022/lib/components/organisms/api-keys-modal/api-keys-modal.i18n.mjs +0 -63
  41. package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.component.mjs +0 -313
  42. package/esm2022/lib/components/organisms/member-import-modal/member-import-modal.i18n.mjs +0 -63
  43. package/esm2022/lib/services/apikeys/api-keys.service.mjs +0 -46
  44. package/esm2022/lib/services/apikeys/types.mjs +0 -7
  45. package/lib/components/organisms/api-keys-modal/api-keys-modal.component.d.ts +0 -44
  46. package/lib/components/organisms/api-keys-modal/api-keys-modal.i18n.d.ts +0 -6
  47. package/lib/components/organisms/member-import-modal/member-import-modal.component.d.ts +0 -47
  48. package/lib/components/organisms/member-import-modal/member-import-modal.i18n.d.ts +0 -6
  49. package/lib/services/apikeys/api-keys.service.d.ts +0 -25
  50. package/lib/services/apikeys/types.d.ts +0 -46
@@ -0,0 +1,146 @@
1
+ import { OnDestroy, OnInit } from '@angular/core';
2
+ import { FormControl } from '@angular/forms';
3
+ import { ToggleInputMetadata } from '../../molecules/toggle-input/types';
4
+ import { ButtonMetadata } from '../../types';
5
+ import { NotificationPermissionState } from '../../../services/auth/types';
6
+ import { PreferencesService } from '../../../services/preferences/preferences.service';
7
+ import { NotificationPreferencesViewConfig } from './types';
8
+ import * as i0 from "@angular/core";
9
+ /**
10
+ * Estados de la vista de preferencias push:
11
+ * - `idle`: toggle off, sin operación en curso, sin errores
12
+ * - `enabling`: secuencia de activación en curso (toggle spinner)
13
+ * - `enabled`: todo OK (master=true + permission=granted + token registrado)
14
+ * - `disabling`: desactivación en curso
15
+ * - `error`: último intento falló → mensaje + botón "Reintentar"
16
+ * - `blocked`: navegador denegó permisos → mensaje + cómo arreglar
17
+ * - `unsupported`: navegador no soporta FCM → mensaje
18
+ * - `needs-install`: iOS sin standalone → instrucciones de instalación PWA
19
+ */
20
+ type UiState = 'idle' | 'enabling' | 'enabled' | 'disabling' | 'error' | 'blocked' | 'unsupported' | 'needs-install';
21
+ /**
22
+ * `val-notification-preferences-view` — **preferencias de notificaciones push**
23
+ * (FCM) full-feature autocontenida (organism). Promovida desde `showcase` bajo el
24
+ * proceso de ADR-021.
25
+ *
26
+ * Separada de `val-notifications-view` (el inbox / feed). Aquí el user **activa o
27
+ * desactiva** las notificaciones push en este dispositivo.
28
+ *
29
+ * UX simplificado: UN solo toggle que ejecuta toda la secuencia (pedir permiso →
30
+ * SW ready → getToken → registrar en backend → set master pref) vía
31
+ * `MessagingService.enable()`. El registro del device en el backend va como
32
+ * callback (la lib no depende de `AuthService` para evitar ciclos). Mensajes
33
+ * contextuales y botón "Reintentar" aparecen solo cuando aplican.
34
+ *
35
+ * NO renderiza ion-content — vive dentro de val-page-wrapper. `ActivatedRoute` se
36
+ * inyecta `{ optional: true }` → funciona sin router (embebida / Storybook).
37
+ */
38
+ export declare class NotificationPreferencesViewComponent implements OnInit, OnDestroy {
39
+ private nav;
40
+ private i18n;
41
+ private toast;
42
+ private auth;
43
+ private messaging;
44
+ private pageRefresh;
45
+ readonly prefs: PreferencesService;
46
+ private route;
47
+ /**
48
+ * Config vía @Input (object-first). Si no se pasa, se cae al route data
49
+ * `notificationPreferencesConfig` (poblado por
50
+ * `provideValtechNotificationPreferencesRoutes`). `resolvedConfig` mergea con
51
+ * los defaults — `@Input` gana sobre route data.
52
+ */
53
+ config?: NotificationPreferencesViewConfig;
54
+ readonly resolvedConfig: import("@angular/core").Signal<Required<Omit<NotificationPreferencesViewConfig, "onPushEnabled" | "onPushDisabled">> & Pick<NotificationPreferencesViewConfig, "onPushEnabled" | "onPushDisabled">>;
55
+ /** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
56
+ private get ns();
57
+ /** Operación en curso (gobierna spinner del toggle + label "Activando…"). */
58
+ private readonly _busy;
59
+ /** True si el último intento falló — gobierna estado `error` + retry button. */
60
+ private readonly _lastFailed;
61
+ /** True mientras se re-obtiene el token FCM en background (no afecta la UI). */
62
+ private _repairingToken;
63
+ /** Toggle del expand de detalles técnicos. */
64
+ readonly showDetails: import("@angular/core").WritableSignal<boolean>;
65
+ readonly permission: import("@angular/core").WritableSignal<NotificationPermissionState>;
66
+ readonly isSupported: import("@angular/core").WritableSignal<boolean>;
67
+ readonly currentToken: import("@angular/core").WritableSignal<string>;
68
+ readonly needsIOSInstall: import("@angular/core").WritableSignal<boolean>;
69
+ /** FormControl del toggle (sync-eado con `isEnabled` via effect). */
70
+ readonly toggleControl: FormControl<boolean>;
71
+ /** Handler del listener `focus` — referencia guardada para poder removerlo. */
72
+ private readonly onWindowFocus;
73
+ /** Timer del debounce del refresh disparado por `focus`. */
74
+ private focusDebounceTimer;
75
+ /** Ventana de debounce (ms) para el refresh disparado por `focus`. */
76
+ private readonly FOCUS_DEBOUNCE_MS;
77
+ readonly pageTitle: import("@angular/core").Signal<string>;
78
+ readonly pageDescription: import("@angular/core").Signal<string>;
79
+ /**
80
+ * Estado efectivo del toggle: "el usuario tiene push activo".
81
+ *
82
+ * Se deriva SOLO de la decisión del usuario (`master`) y del permiso del SO
83
+ * (`permission`). El token FCM NO forma parte del estado de UI: vive en
84
+ * memoria, se pierde en cada recarga/suspensión de la PWA y produciría flicker.
85
+ * Si falta token con `master && granted`, es un detalle reparable en
86
+ * background (ver `repairTokenIfNeeded`), no un cambio del toggle.
87
+ */
88
+ readonly isEnabled: import("@angular/core").Signal<boolean>;
89
+ readonly state: import("@angular/core").Signal<UiState>;
90
+ readonly busyLabel: import("@angular/core").Signal<string>;
91
+ readonly contextMessage: import("@angular/core").Signal<string>;
92
+ readonly alertVariant: import("@angular/core").Signal<"warning" | "danger" | "info">;
93
+ readonly alertIcon: import("@angular/core").Signal<"alert-circle-outline" | "close-circle-outline">;
94
+ readonly toggleProps: import("@angular/core").Signal<ToggleInputMetadata>;
95
+ readonly retryButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
96
+ readonly tokenPreview: import("@angular/core").Signal<string>;
97
+ constructor();
98
+ /**
99
+ * Registra el pull-to-refresh estándar. Aunque esta vista no muestra una
100
+ * lista remota, sí refleja estado mutable del browser (permiso, token,
101
+ * soporte FCM) que puede cambiar fuera de la app — el refresh re-evalúa todo.
102
+ *
103
+ * Se usa `ngOnInit`/`ngOnDestroy` (NO `ionViewWillEnter`) porque
104
+ * `val-page-wrapper` usa `<router-outlet>` plano — los hooks `ionView*` solo
105
+ * disparan dentro de `<ion-router-outlet>`.
106
+ */
107
+ ngOnInit(): void;
108
+ ngOnDestroy(): void;
109
+ /** Refresca el estado del browser con debounce — evita ráfagas de `focus`. */
110
+ private scheduleBrowserRefresh;
111
+ /**
112
+ * Secuencia completa de activación.
113
+ *
114
+ * Toda la mecánica (permission → SW ready → getToken con retry → watchdog de
115
+ * auto-reload) vive en `MessagingService.enable()` de la lib. El paso de
116
+ * registro del device en el backend se pasa como callback (`registerDevice`)
117
+ * porque la lib no puede depender de `AuthService` sin crear un ciclo.
118
+ *
119
+ * `enable()` no hace throw: resuelve con un `EnablePushResult` descriptivo.
120
+ */
121
+ onEnable(): Promise<void>;
122
+ onDisable(): Promise<void>;
123
+ /** Reintentar la secuencia completa de activación, sin importar el estado actual. */
124
+ onRetry(): Promise<void>;
125
+ toggleDetails(): void;
126
+ private refreshBrowserState;
127
+ /**
128
+ * Repara el token FCM en background.
129
+ *
130
+ * Si el usuario tiene push activo (`master && granted`) pero no hay token en
131
+ * memoria — caso típico tras un cold start de la PWA — re-obtenemos el token
132
+ * y re-registramos el device sin tocar el toggle ni mostrar un error
133
+ * alarmista. El token es un detalle de implementación reparable, no parte del
134
+ * estado de UI (ver `isEnabled`).
135
+ */
136
+ private repairTokenIfNeeded;
137
+ /**
138
+ * iOS browser sin estar instalado como PWA — push web no disponible.
139
+ * Aplica a Safari y a Edge/Chrome/Firefox en iOS (todos WebKit por mandato Apple).
140
+ */
141
+ private detectNeedsIOSInstall;
142
+ protected tt(key: string): string;
143
+ static ɵfac: i0.ɵɵFactoryDeclaration<NotificationPreferencesViewComponent, never>;
144
+ static ɵcmp: i0.ɵɵComponentDeclaration<NotificationPreferencesViewComponent, "val-notification-preferences-view", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
145
+ }
146
+ export {};
@@ -0,0 +1,11 @@
1
+ import { LanguagesContent } from '../../../services/i18n/types';
2
+ /**
3
+ * Defaults i18n (es/en) embebidos en `val-notification-preferences-view`.
4
+ * Auto-registrados en el constructor del componente si el consumer no proveyó
5
+ * el namespace (`Settings.Notifications` por default). SOLO incluye las keys que
6
+ * la vista usa.
7
+ *
8
+ * Portado del override `Settings.Notifications` (showcase) bajo el proceso de
9
+ * ADR-021.
10
+ */
11
+ export declare const NOTIFICATION_PREFERENCES_VIEW_I18N: LanguagesContent;
@@ -0,0 +1,26 @@
1
+ import { Routes } from '@angular/router';
2
+ import { NotificationPreferencesViewConfig } from './types';
3
+ /**
4
+ * Helper para montar las **preferencias de notificaciones push**
5
+ * (`val-notification-preferences-view`) como ruta en una app del factory. El
6
+ * `config` se pasa por route `data` (`notificationPreferencesConfig`) y el
7
+ * componente lo lee como fallback de su `@Input() config`.
8
+ *
9
+ * No confundir con `provideValtechNotificationsRoutes` (el inbox / feed).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * // app.routes.ts (típicamente bajo settings)
14
+ * export const settingsRoutes: Routes = [
15
+ * ...provideValtechNotificationPreferencesRoutes(), // → notifications
16
+ * ];
17
+ *
18
+ * // con config acotada:
19
+ * ...provideValtechNotificationPreferencesRoutes({ config: { showDetails: false } }),
20
+ * ...provideValtechNotificationPreferencesRoutes({ path: 'push' }),
21
+ * ```
22
+ */
23
+ export declare function provideValtechNotificationPreferencesRoutes(opts?: {
24
+ path?: string;
25
+ config?: NotificationPreferencesViewConfig;
26
+ }): Routes;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Configuración acotada de `val-notification-preferences-view` (object-first).
3
+ * Tres ejes de variación permitidos — **NADA de slots arbitrarios** (ADR-021:
4
+ * una vista full-feature no abre slots; si falta algo, se promueve un nuevo
5
+ * punto de extensión):
6
+ *
7
+ * - **secciones / flags** — gatean el render de bloques opcionales (panel de
8
+ * detalles técnicos expandible).
9
+ * - **branding** — `i18nNamespace` para resolver los textos (default
10
+ * `'Settings.Notifications'`).
11
+ * - **comportamiento / callbacks** — `onPushEnabled` / `onPushDisabled`
12
+ * (telemetría tras activar/desactivar push).
13
+ */
14
+ export interface NotificationPreferencesViewConfig {
15
+ /**
16
+ * Muestra el panel "Ver detalles técnicos" (token FCM, permiso del navegador,
17
+ * soporte). Se oculta de todos modos en los estados `unsupported` y
18
+ * `needs-install`. Default `true`.
19
+ */
20
+ showDetails?: boolean;
21
+ /**
22
+ * Namespace i18n con el que la vista resuelve sus textos.
23
+ * Default `'Settings.Notifications'`.
24
+ */
25
+ i18nNamespace?: string;
26
+ /**
27
+ * Hook de telemetría tras activar push correctamente (permiso concedido +
28
+ * token registrado + master en `true`).
29
+ */
30
+ onPushEnabled?: () => void;
31
+ /**
32
+ * Hook de telemetría tras desactivar push (device desregistrado + master en
33
+ * `false`).
34
+ */
35
+ onPushDisabled?: () => void;
36
+ }
@@ -61,7 +61,6 @@ export declare class OrganizationViewComponent {
61
61
  readonly members: import("@angular/core").WritableSignal<MemberDetail[]>;
62
62
  readonly membersLoading: import("@angular/core").WritableSignal<boolean>;
63
63
  private readonly membersLoadError;
64
- readonly membersErrorState: import("@angular/core").Signal<EmptyStateMetadata>;
65
64
  readonly membersNextToken: import("@angular/core").WritableSignal<string>;
66
65
  readonly loadingMoreMembers: import("@angular/core").WritableSignal<boolean>;
67
66
  readonly showAllMembers: import("@angular/core").WritableSignal<boolean>;
@@ -82,16 +81,12 @@ export declare class OrganizationViewComponent {
82
81
  readonly viewPermissionsButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
83
82
  readonly transferButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
84
83
  readonly openInviteButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
85
- readonly openImportButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
86
- readonly openApiKeysButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
87
84
  /** Guarda para detectar el primer disparo del effect (evita doble carga). */
88
85
  private lastLoadedOrgId;
89
86
  constructor();
90
87
  onEdit(): void;
91
88
  onLeave(): Promise<void>;
92
89
  onOpenInvite(): void;
93
- onOpenImport(): void;
94
- onOpenApiKeys(): void;
95
90
  onViewPermissions(): void;
96
91
  onOpenTransfer(): void;
97
92
  onTransfer(newOwnerId: string): Promise<void>;
@@ -0,0 +1,71 @@
1
+ import { ButtonMetadata } from '../../types';
2
+ import { PermissionsViewConfig } from './types';
3
+ import * as i0 from "@angular/core";
4
+ interface PermGroupView {
5
+ key: string;
6
+ label: string;
7
+ perms: string[];
8
+ }
9
+ interface RoleView {
10
+ id: string;
11
+ name: string;
12
+ description?: string;
13
+ isSystem: boolean;
14
+ groups: PermGroupView[];
15
+ hasPerms: boolean;
16
+ }
17
+ /**
18
+ * `val-permissions-view` — vista Permisos full-feature autocontenida (organism).
19
+ * Visor RBAC de solo lectura: muestra los roles del sistema (Visor/Editor/Admin +
20
+ * roles de plataforma) y los roles personalizados de la org activa, con el
21
+ * catálogo de permisos agrupado por alcance (app actual / plataforma / otras apps).
22
+ * Promovida desde `showcase` bajo el proceso de ADR-021.
23
+ *
24
+ * **RBAC interno** (como `organization-view`): lee la org activa vía
25
+ * `AuthService.user().activeOrgId`. La vista NO muta nada — el control de quién
26
+ * puede verla es responsabilidad del guard de ruta del consumer; no hay gating
27
+ * fino interno ni se expone como config.
28
+ *
29
+ * Datos: `forkJoin` de `OrgService.listOrgRoles(orgId)` (roles de la org) +
30
+ * `PermissionCatalogService.getCatalog(orgId)` (catálogo + appId actual). El
31
+ * catálogo define el alcance (`scope`/`appId`) de cada recurso para agrupar.
32
+ *
33
+ * NO renderiza ion-content — vive dentro de val-page-wrapper. `ActivatedRoute` se
34
+ * inyecta `{ optional: true }` solo para leer el route data de config. Auto-registra
35
+ * sus defaults i18n (es/en) si el consumer no proveyó el namespace (default
36
+ * `Settings.Permissions`).
37
+ */
38
+ export declare class PermissionsViewComponent {
39
+ private i18n;
40
+ private orgService;
41
+ private catalog;
42
+ private auth;
43
+ private nav;
44
+ private route;
45
+ /**
46
+ * Config vía @Input (object-first). Si no se pasa, se cae al route data
47
+ * `permissionsConfig` (poblado por `provideValtechPermissionsRoutes`).
48
+ * `resolvedConfig` mergea con los defaults — `@Input` gana sobre route data.
49
+ */
50
+ config?: PermissionsViewConfig;
51
+ readonly resolvedConfig: import("@angular/core").Signal<Required<PermissionsViewConfig>>;
52
+ /** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
53
+ private get ns();
54
+ readonly loading: import("@angular/core").WritableSignal<boolean>;
55
+ readonly loadError: import("@angular/core").WritableSignal<unknown>;
56
+ private readonly roles;
57
+ readonly systemRoles: import("@angular/core").Signal<RoleView[]>;
58
+ readonly customRoles: import("@angular/core").Signal<RoleView[]>;
59
+ readonly activeOrgId: import("@angular/core").Signal<string>;
60
+ readonly retryButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
61
+ constructor();
62
+ load(): void;
63
+ private buildRoleView;
64
+ protected tt(key: string): string;
65
+ appLabel(appId: string): string;
66
+ roleLabel(name: string): string;
67
+ permLabel(resource: string, action: string): string;
68
+ static ɵfac: i0.ɵɵFactoryDeclaration<PermissionsViewComponent, never>;
69
+ static ɵcmp: i0.ɵɵComponentDeclaration<PermissionsViewComponent, "val-permissions-view", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
70
+ }
71
+ export {};
@@ -0,0 +1,9 @@
1
+ import { LanguagesContent } from '../../../services/i18n/types';
2
+ /**
3
+ * Defaults i18n (es/en) embebidos en `val-permissions-view`. Auto-registrados en
4
+ * el constructor del componente si el consumer no proveyó el namespace
5
+ * (`Settings.Permissions` por default). SOLO incluye las keys que la vista usa.
6
+ *
7
+ * Portado EXACTO de `PERMISSIONS_I18N` (showcase) bajo el proceso de ADR-021.
8
+ */
9
+ export declare const PERMISSIONS_VIEW_I18N: LanguagesContent;
@@ -0,0 +1,24 @@
1
+ import { Routes } from '@angular/router';
2
+ import { PermissionsViewConfig } from './types';
3
+ /**
4
+ * Helper para montar la vista Permisos (`val-permissions-view`) como ruta en una
5
+ * app del factory. El `config` se pasa por route `data` (`permissionsConfig`) y el
6
+ * componente lo lee como fallback de su `@Input() config`.
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * // settings.routes.ts
11
+ * export const settingsRoutes: Routes = [
12
+ * ...provideValtechPermissionsRoutes(), // → /app/settings/permissions
13
+ * { path: 'preferences', loadComponent: () => ... },
14
+ * ];
15
+ *
16
+ * // con config acotada:
17
+ * ...provideValtechPermissionsRoutes({ config: { showCustomRoles: false } }),
18
+ * ...provideValtechPermissionsRoutes({ path: 'roles' }),
19
+ * ```
20
+ */
21
+ export declare function provideValtechPermissionsRoutes(opts?: {
22
+ path?: string;
23
+ config?: PermissionsViewConfig;
24
+ }): Routes;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Configuración acotada de `val-permissions-view` (object-first). Tres ejes de
3
+ * variación permitidos — **NADA de slots arbitrarios** (ADR-021: una vista
4
+ * full-feature no abre slots; si falta algo, se promueve un nuevo punto de
5
+ * extensión):
6
+ *
7
+ * - **secciones visibles** — gatean el render de cada bloque (roles del sistema,
8
+ * roles personalizados). El acceso a la vista en sí (¿quién puede ver
9
+ * permisos?) es responsabilidad del guard de ruta del consumer; la vista es
10
+ * de solo lectura y no muta nada, por lo que no hay gating RBAC fino interno —
11
+ * solo lee la org activa vía `AuthService` (como `organization-view`). Estos
12
+ * flags solo permiten ocultar la sección por completo.
13
+ * - **branding** — `i18nNamespace` para resolver los textos (default
14
+ * `'Settings.Permissions'`).
15
+ */
16
+ export interface PermissionsViewConfig {
17
+ /** Muestra la sección "Roles del sistema". Default `true`. */
18
+ showSystemRoles?: boolean;
19
+ /** Muestra la sección "Roles personalizados". Default `true`. */
20
+ showCustomRoles?: boolean;
21
+ /**
22
+ * Namespace i18n con el que la vista resuelve sus textos.
23
+ * Default `'Settings.Permissions'`.
24
+ */
25
+ i18nNamespace?: string;
26
+ }
@@ -1,6 +1,9 @@
1
1
  import { Routes } from '@angular/router';
2
2
  import { ProfileViewConfig } from '../profile-view/types';
3
3
  import { PreferencesViewConfig } from '../preferences-view/types';
4
+ import { SecurityViewConfig } from '../security-view/types';
5
+ import { AccountViewConfig } from '../account-view/types';
6
+ import { OrganizationViewConfig } from '../organization-view/types';
4
7
  import { SettingsHubConfig } from './types';
5
8
  /**
6
9
  * Opciones de `provideValtechSettingsRoutes`. Agrupa el HUB (`val-settings-hub`)
@@ -17,10 +20,22 @@ export interface ValtechSettingsRoutesOptions {
17
20
  profileConfig?: ProfileViewConfig;
18
21
  /** Config de la vista Preferencias (pass-through a `provideValtechPreferencesRoutes`). */
19
22
  preferencesConfig?: PreferencesViewConfig;
23
+ /** Config de la vista Seguridad (pass-through a `provideValtechSecurityRoutes`). */
24
+ securityConfig?: SecurityViewConfig;
25
+ /** Config de la vista Cuenta (pass-through a `provideValtechAccountRoutes`). */
26
+ accountConfig?: AccountViewConfig;
27
+ /** Config de la vista Gestión de organización (pass-through a `provideValtechOrganizationRoutes`). */
28
+ organizationConfig?: OrganizationViewConfig;
20
29
  /** Monta la ruta `profile`. Default `true`. */
21
30
  includeProfile?: boolean;
22
31
  /** Monta la ruta de preferencias. Default `true`. */
23
32
  includePreferences?: boolean;
33
+ /** Monta la ruta `security`. Default `true`. */
34
+ includeSecurity?: boolean;
35
+ /** Monta la ruta `account`. Default `true`. */
36
+ includeAccount?: boolean;
37
+ /** Monta la ruta `organization`. Default `true`. */
38
+ includeOrganization?: boolean;
24
39
  /** Path de la vista Preferencias. Default `'preferences'`. */
25
40
  preferencesPath?: string;
26
41
  /** Rutas extra a sumar como hijas (secciones de la app no promovidas). */
@@ -6,7 +6,7 @@ import { AuthStateService } from './auth-state.service';
6
6
  import { TokenService } from './token.service';
7
7
  import { AuthStorageService } from './storage.service';
8
8
  import { AuthSyncService } from './sync.service';
9
- import { SigninRequest, SigninResponse, SignupRequest, SignupResponse, VerifyEmailRequest, VerifyEmailResponse, ResendCodeRequest, ResendCodeResponse, MFAVerifyResponse, RefreshResponse, GetPermissionsResponse, GetProfileResponse, UpdateProfileRequest, UpdateProfileResponse, MFASetupResponse, MFAConfirmResponse, MFADisableRequest, MFADisableResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, ActivateAccountRequest, ActivateAccountResponse, ChangePasswordResponse, DeleteAccountResponse, SendDeleteAccountCodeResponse, SwitchOrgResponse, MFAMethod, AuthError, ValtechAuthConfig, EnableNotificationsResult, NotificationPermissionState, RegisterDeviceResult, TOTPSetupResponse, TOTPVerifySetupResponse, TOTPDisableResponse, RegenerateBackupCodesResponse, BackupCodesCountResponse, OAuthProvider, LinkedProvider, HasPasswordResponse, UpdateHandleResponse, CheckHandleResponse, UpdateAvatarRequest, UpdateAvatarResponse, InitiateEmailChangeResponse, ConfirmEmailChangeStep1Response, ConfirmEmailChangeStep2Response } from './types';
9
+ import { SigninRequest, SigninResponse, SignupRequest, SignupResponse, VerifyEmailRequest, VerifyEmailResponse, ResendCodeRequest, ResendCodeResponse, MFAVerifyResponse, RefreshResponse, GetPermissionsResponse, GetProfileResponse, UpdateProfileRequest, UpdateProfileResponse, MFASetupResponse, MFAConfirmResponse, MFADisableRequest, MFADisableResponse, ForgotPasswordRequest, ForgotPasswordResponse, ResetPasswordRequest, ResetPasswordResponse, ChangePasswordResponse, DeleteAccountResponse, SendDeleteAccountCodeResponse, SwitchOrgResponse, MFAMethod, AuthError, ValtechAuthConfig, EnableNotificationsResult, NotificationPermissionState, RegisterDeviceResult, TOTPSetupResponse, TOTPVerifySetupResponse, TOTPDisableResponse, RegenerateBackupCodesResponse, BackupCodesCountResponse, OAuthProvider, LinkedProvider, HasPasswordResponse, UpdateHandleResponse, CheckHandleResponse, UpdateAvatarRequest, UpdateAvatarResponse, InitiateEmailChangeResponse, ConfirmEmailChangeStep1Response, ConfirmEmailChangeStep2Response } from './types';
10
10
  import { OAuthService } from './oauth.service';
11
11
  import { FirebaseService, MessagingService } from '../firebase';
12
12
  import { I18nService } from '../i18n';
@@ -288,12 +288,6 @@ export declare class AuthService implements OnDestroy {
288
288
  * Resetea la contraseña usando el código enviado por email.
289
289
  */
290
290
  resetPassword(request: ResetPasswordRequest): Observable<ResetPasswordResponse>;
291
- /**
292
- * Activa una cuenta pre-aprovisionada por una organización (ADR-023): define
293
- * la contraseña con el token del enlace de email. En éxito el backend devuelve
294
- * tokens de auto-signin → el usuario queda logueado (mismo flujo que verify-email).
295
- */
296
- activateAccount(request: ActivateAccountRequest): Observable<ActivateAccountResponse>;
297
291
  /**
298
292
  * Cambia la contraseña del usuario autenticado.
299
293
  * Requiere la contraseña actual para verificación.
@@ -238,29 +238,6 @@ export interface VerifyEmailResponse {
238
238
  expiresIn?: number;
239
239
  tokenType?: string;
240
240
  }
241
- /**
242
- * Request para activar una cuenta pre-aprovisionada por una organización
243
- * (ADR-023): el usuario define su contraseña con el token del enlace de email.
244
- */
245
- export interface ActivateAccountRequest {
246
- token: string;
247
- newPassword: string;
248
- }
249
- /**
250
- * Response de activación de cuenta. En éxito incluye tokens de auto-signin
251
- * (mismo shape que verify-email) — el usuario queda logueado tras activar.
252
- */
253
- export interface ActivateAccountResponse {
254
- operationId: string;
255
- activated: boolean;
256
- accessToken?: string;
257
- refreshToken?: string;
258
- firebaseToken?: string;
259
- expiresIn?: number;
260
- tokenType?: string;
261
- roles?: string[];
262
- permissions?: string[];
263
- }
264
241
  /**
265
242
  * Request para reenviar código de verificación.
266
243
  */
@@ -1,7 +1,7 @@
1
1
  import { HttpClient } from '@angular/common/http';
2
2
  import { Observable } from 'rxjs';
3
3
  import { ValtechAuthConfig } from '../auth/types';
4
- import { Organization, ListMyOrgsResponse, CreateOrgRequest, UpdateOrgRequest, InviteUserRequest, InviteUserResponse, LeaveOrgResponse, ListOrgMembersResponse, OrgRole, ChangeMemberRoleResponse, PendingInvitation, AcceptInvitationResponse, ImportMembersRequest, ImportMembersResponse } from './types';
4
+ import { Organization, ListMyOrgsResponse, CreateOrgRequest, UpdateOrgRequest, InviteUserRequest, InviteUserResponse, LeaveOrgResponse, ListOrgMembersResponse, OrgRole, ChangeMemberRoleResponse, PendingInvitation, AcceptInvitationResponse } from './types';
5
5
  import * as i0 from "@angular/core";
6
6
  export declare class OrgService {
7
7
  private config;
@@ -21,11 +21,6 @@ export declare class OrgService {
21
21
  message: string;
22
22
  }>;
23
23
  inviteUser(orgId: string, req: InviteUserRequest): Observable<InviteUserResponse>;
24
- /**
25
- * Crea/asigna miembros en masa (ADR-023). Resultado por-fila (partial success):
26
- * `created` (pre-aprovisionado), `assigned` (ya existía), `skipped`, `error`.
27
- */
28
- importMembers(orgId: string, req: ImportMembersRequest): Observable<ImportMembersResponse>;
29
24
  leaveOrg(orgId: string): Observable<LeaveOrgResponse>;
30
25
  getOrgMembers(orgId: string, params?: {
31
26
  limit?: number;
@@ -0,0 +1,34 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { Observable } from 'rxjs';
3
+ import { ValtechAuthConfig } from '../auth/types';
4
+ import * as i0 from "@angular/core";
5
+ export type PermissionScope = 'global' | 'app';
6
+ export interface PermissionResource {
7
+ resource: string;
8
+ scope: PermissionScope;
9
+ appId?: string;
10
+ actions: string[];
11
+ }
12
+ export interface PermissionCatalogResponse {
13
+ operationId: string;
14
+ appId: string;
15
+ permissions: PermissionResource[];
16
+ }
17
+ /**
18
+ * Consume el catálogo de permisos del backend (`GET /org/{orgId}/permissions-catalog`).
19
+ * El backend es la fuente de verdad de qué permisos existen y de su alcance
20
+ * (globales de plataforma vs. propios de una app). La respuesta incluye el
21
+ * `appId` del request para que la vista distinga la app actual.
22
+ *
23
+ * Promovido desde `showcase` a la lib bajo el proceso de ADR-021. Usa
24
+ * `VALTECH_AUTH_CONFIG.apiUrl` (como `OrgService`) en vez del `environment` de la
25
+ * app — la lib no importa el environment del consumer.
26
+ */
27
+ export declare class PermissionCatalogService {
28
+ private config;
29
+ private http;
30
+ constructor(config: ValtechAuthConfig, http: HttpClient);
31
+ getCatalog(orgId: string): Observable<PermissionCatalogResponse>;
32
+ static ɵfac: i0.ɵɵFactoryDeclaration<PermissionCatalogService, never>;
33
+ static ɵprov: i0.ɵɵInjectableDeclaration<PermissionCatalogService>;
34
+ }
@@ -97,33 +97,3 @@ export interface ChangeMemberRoleResponse {
97
97
  orgId: string;
98
98
  roleId: string;
99
99
  }
100
- export type ImportOnConflict = 'assignRole' | 'skip' | 'error';
101
- export interface ImportUserRow {
102
- email: string;
103
- name?: string;
104
- roleName: string;
105
- }
106
- export interface ImportMembersRequest {
107
- users: ImportUserRow[];
108
- onConflict?: ImportOnConflict;
109
- sendActivation?: boolean;
110
- }
111
- export type ImportRowStatus = 'created' | 'assigned' | 'skipped' | 'error';
112
- export interface ImportRowResult {
113
- email: string;
114
- status: ImportRowStatus;
115
- userId?: string;
116
- activation?: 'sent' | 'pending';
117
- reason?: string;
118
- }
119
- export interface ImportSummary {
120
- created: number;
121
- assigned: number;
122
- skipped: number;
123
- failed: number;
124
- }
125
- export interface ImportMembersResponse {
126
- operationId: string;
127
- summary: ImportSummary;
128
- results: ImportRowResult[];
129
- }
package/lib/version.d.ts CHANGED
@@ -2,4 +2,4 @@
2
2
  * Current version of valtech-components.
3
3
  * This is automatically updated during the publish process.
4
4
  */
5
- export declare const VERSION = "2.0.996";
5
+ export declare const VERSION = "2.0.997";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valtech-components",
3
- "version": "2.0.996",
3
+ "version": "2.0.997",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "valtech-firebase-config": "./src/lib/services/firebase/scripts/generate-sw-config.js"
package/public-api.d.ts CHANGED
@@ -287,6 +287,13 @@ export * from './lib/components/organisms/organization-view/organization.routes'
287
287
  export * from './lib/components/organisms/notifications-view/notifications-view.component';
288
288
  export * from './lib/components/organisms/notifications-view/types';
289
289
  export * from './lib/components/organisms/notifications-view/notifications.routes';
290
+ export * from './lib/components/organisms/notification-preferences-view/notification-preferences-view.component';
291
+ export * from './lib/components/organisms/notification-preferences-view/types';
292
+ export * from './lib/components/organisms/notification-preferences-view/notification-preferences.routes';
293
+ export * from './lib/components/organisms/permissions-view/permissions-view.component';
294
+ export * from './lib/components/organisms/permissions-view/types';
295
+ export * from './lib/components/organisms/permissions-view/permissions.routes';
296
+ export * from './lib/services/org/permission-catalog.service';
290
297
  export * from './lib/components/organisms/delete-account-modal/delete-account-modal.component';
291
298
  export * from './lib/components/organisms/switch-org-modal/switch-org-modal.component';
292
299
  export * from './lib/components/organisms/create-org-modal/create-org-modal.component';
@@ -294,8 +301,6 @@ export * from './lib/components/organisms/org-info-sheet/org-info-sheet.componen
294
301
  export * from './lib/components/organisms/invite-member-modal/invite-member-modal.component';
295
302
  export * from './lib/components/organisms/member-detail-modal/member-detail-modal.component';
296
303
  export * from './lib/components/organisms/member-detail-modal/types';
297
- export * from './lib/components/organisms/member-import-modal/member-import-modal.component';
298
- export * from './lib/components/organisms/api-keys-modal/api-keys-modal.component';
299
304
  export * from './lib/components/organisms/edit-org-modal/edit-org-modal.component';
300
305
  export * from './lib/components/organisms/transfer-ownership-modal/transfer-ownership-modal.component';
301
306
  export * from './lib/components/organisms/transfer-ownership-modal/types';
@@ -342,9 +347,7 @@ export * from './lib/services/legal-link/legal-link.service';
342
347
  export * from './lib/services/firebase';
343
348
  export * from './lib/services/auth';
344
349
  export { OrgService } from './lib/services/org/org.service';
345
- export type { Organization, OrgType, OrgPlan, CreateOrgRequest, UpdateOrgRequest, InviteUserRequest, InviteUserResponse, LeaveOrgResponse, ListMyOrgsResponse, OrgResponse, OrgMember, ListOrgMembersResponse, PendingInvitation, ListPendingInvitationsResponse, AcceptInvitationResponse, OrgRole, ListOrgRolesResponse, ChangeMemberRoleRequest, ChangeMemberRoleResponse, ImportUserRow, ImportOnConflict, ImportMembersRequest, ImportRowStatus, ImportRowResult, ImportSummary, ImportMembersResponse, } from './lib/services/org/types';
346
- export { ApiKeyService } from './lib/services/apikeys/api-keys.service';
347
- export type { ClientApiKey, ClientApiKeyWithSecret, CreateApiKeyRequest, CreateApiKeyResponse, ListApiKeysResponse, AvailablePermissionsResponse, RevokeApiKeyResponse, } from './lib/services/apikeys/types';
350
+ export type { Organization, OrgType, OrgPlan, CreateOrgRequest, UpdateOrgRequest, InviteUserRequest, InviteUserResponse, LeaveOrgResponse, ListMyOrgsResponse, OrgResponse, OrgMember, ListOrgMembersResponse, PendingInvitation, ListPendingInvitationsResponse, AcceptInvitationResponse, OrgRole, ListOrgRolesResponse, ChangeMemberRoleRequest, ChangeMemberRoleResponse, } from './lib/services/org/types';
348
351
  export * from './lib/services/i18n';
349
352
  export * from './lib/services/preferences';
350
353
  export * from './lib/services/network-status';