valtech-components 2.0.983 → 2.0.984
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/login-attempt-modal/login-attempt-modal.component.mjs +298 -0
- package/esm2022/lib/components/organisms/security-view/security-view.component.mjs +819 -0
- package/esm2022/lib/components/organisms/security-view/security-view.i18n.mjs +105 -0
- package/esm2022/lib/components/organisms/security-view/security.routes.mjs +29 -0
- package/esm2022/lib/components/organisms/security-view/types.mjs +2 -0
- package/esm2022/lib/components/organisms/session-list-modal/session-list-modal.component.mjs +206 -0
- package/esm2022/lib/components/organisms/session-list-modal/types.mjs +2 -0
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +7 -1
- package/fesm2022/valtech-components.mjs +2393 -988
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/login-attempt-modal/login-attempt-modal.component.d.ts +58 -0
- package/lib/components/organisms/security-view/security-view.component.d.ts +130 -0
- package/lib/components/organisms/security-view/security-view.i18n.d.ts +12 -0
- package/lib/components/organisms/security-view/security.routes.d.ts +24 -0
- package/lib/components/organisms/security-view/types.d.ts +48 -0
- package/lib/components/organisms/session-list-modal/session-list-modal.component.d.ts +56 -0
- package/lib/components/organisms/session-list-modal/types.d.ts +27 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +6 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { ButtonMetadata } from '../../types';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* `val-login-attempt-modal` — modal de confirmación de intento de inicio de sesión.
|
|
5
|
+
*
|
|
6
|
+
* Se abre cuando el usuario llega a la vista Seguridad vía
|
|
7
|
+
* `?token=...` desde el email/push de "nuevo acceso". Muestra el dispositivo
|
|
8
|
+
* detectado y dos acciones: confirmar que fue uno mismo (cierra sin hacer nada)
|
|
9
|
+
* o bloquear el dispositivo (ejecuta el token de acción).
|
|
10
|
+
*
|
|
11
|
+
* Inputs vía `componentProps` del ModalService. Sin `@Output` (no funcionan con
|
|
12
|
+
* `modalController.create()`) — usa callback `onBlock` y `_modalRef.dismiss`.
|
|
13
|
+
* Recibe los labels ya traducidos (agnóstico a i18n).
|
|
14
|
+
*
|
|
15
|
+
* Header canónico (Regla #5): sin `ion-title`, botón Cerrar texto en `slot=end`,
|
|
16
|
+
* título en el body con `val-display`.
|
|
17
|
+
*/
|
|
18
|
+
export declare class LoginAttemptModalComponent {
|
|
19
|
+
/** Título del modal (i18n ya resuelto). */
|
|
20
|
+
title: string;
|
|
21
|
+
/** Texto explicativo. */
|
|
22
|
+
body: string;
|
|
23
|
+
/** Descripción del dispositivo (navegador · OS · ubicación). */
|
|
24
|
+
deviceLabel: string;
|
|
25
|
+
/** Metadata secundaria (fecha, IP). Opcional. */
|
|
26
|
+
metaLabel: string;
|
|
27
|
+
/** Mensaje mostrado tras bloquear. */
|
|
28
|
+
doneLabel: string;
|
|
29
|
+
/** Labels de botones. */
|
|
30
|
+
mineLabel: string;
|
|
31
|
+
blockLabel: string;
|
|
32
|
+
closeLabel: string;
|
|
33
|
+
/** `true` si el dispositivo es móvil — cambia el icono. */
|
|
34
|
+
isMobile: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Callback que ejecuta el bloqueo (executeAction con el token) contra el
|
|
37
|
+
* backend. Lo provee el parent vía `componentProps`. Debe lanzar si falla.
|
|
38
|
+
*/
|
|
39
|
+
onBlock?: () => Promise<void>;
|
|
40
|
+
/** Inyectado por `ModalService.open` — referencia para cerrar. */
|
|
41
|
+
_modalRef?: {
|
|
42
|
+
dismiss: (data?: unknown, role?: string) => void;
|
|
43
|
+
};
|
|
44
|
+
/** `true` tras bloquear con éxito — cambia el modal a estado "hecho". */
|
|
45
|
+
protected readonly done: import("@angular/core").WritableSignal<boolean>;
|
|
46
|
+
private working;
|
|
47
|
+
get deviceIcon(): string;
|
|
48
|
+
/** "Sí, fui yo" — cierra sin acción. El dispositivo ya está activo. */
|
|
49
|
+
confirmMine(): void;
|
|
50
|
+
/** "No fui yo" — ejecuta el bloqueo y pasa a estado done. */
|
|
51
|
+
confirmBlock(): Promise<void>;
|
|
52
|
+
close(): void;
|
|
53
|
+
get mineBtn(): Partial<ButtonMetadata>;
|
|
54
|
+
get blockBtn(): Partial<ButtonMetadata>;
|
|
55
|
+
get closeBtn(): Partial<ButtonMetadata>;
|
|
56
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<LoginAttemptModalComponent, never>;
|
|
57
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<LoginAttemptModalComponent, "val-login-attempt-modal", never, { "title": { "alias": "title"; "required": false; }; "body": { "alias": "body"; "required": false; }; "deviceLabel": { "alias": "deviceLabel"; "required": false; }; "metaLabel": { "alias": "metaLabel"; "required": false; }; "doneLabel": { "alias": "doneLabel"; "required": false; }; "mineLabel": { "alias": "mineLabel"; "required": false; }; "blockLabel": { "alias": "blockLabel"; "required": false; }; "closeLabel": { "alias": "closeLabel"; "required": false; }; "isMobile": { "alias": "isMobile"; "required": false; }; "onBlock": { "alias": "onBlock"; "required": false; }; "_modalRef": { "alias": "_modalRef"; "required": false; }; }, {}, never, never, true, never>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { ActionCardMetadata } from '../../molecules/action-card/types';
|
|
2
|
+
import { ActionHeaderMetadata } from '../../molecules/action-header/types';
|
|
3
|
+
import { PageLinksMetadata } from '../../molecules/page-links/types';
|
|
4
|
+
import { ButtonMetadata } from '../../types';
|
|
5
|
+
import { DeviceInfo, SessionInfo } from '../../../services/auth/types';
|
|
6
|
+
import { SecurityViewConfig } from './types';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
/**
|
|
9
|
+
* `val-security-view` — vista Seguridad full-feature autocontenida (organism).
|
|
10
|
+
*
|
|
11
|
+
* Promovida desde `showcase` bajo el proceso de ADR-021. Reúne en una sola vista:
|
|
12
|
+
* - **Sesiones activas** — única vista user-facing de "dónde tengo sesión".
|
|
13
|
+
* Lista inline (limit 3) + modal "Ver todas" (`val-session-list-modal`) +
|
|
14
|
+
* revoke individual / revoke-all (con confirmación).
|
|
15
|
+
* - **Action-cards** — cambiar contraseña, cambiar email y MFA (cada una abre
|
|
16
|
+
* el modal correspondiente de la lib).
|
|
17
|
+
* - **Políticas legales** — links resueltos vía `LegalLinkService` (apps
|
|
18
|
+
* satélite apuntan al main site).
|
|
19
|
+
*
|
|
20
|
+
* Deep-links del email (gateados por `config.handleDeepLinks`, default `true`):
|
|
21
|
+
* - `?token=...&action=...` → modal `val-login-attempt-modal` (autorizar/bloquear
|
|
22
|
+
* el nuevo acceso).
|
|
23
|
+
* - `?mfaCode=...` → abre el modal MFA con el código pre-cargado.
|
|
24
|
+
*
|
|
25
|
+
* NO renderiza ion-content — vive dentro de val-page-wrapper.
|
|
26
|
+
*
|
|
27
|
+
* Auto-registra sus defaults i18n (es/en) en el constructor si el consumer no
|
|
28
|
+
* proveyó el namespace configurado (default `Settings.Security`).
|
|
29
|
+
*/
|
|
30
|
+
export declare class SecurityViewComponent {
|
|
31
|
+
private nav;
|
|
32
|
+
private i18n;
|
|
33
|
+
private deviceService;
|
|
34
|
+
private legalLink;
|
|
35
|
+
private toast;
|
|
36
|
+
private errors;
|
|
37
|
+
private router;
|
|
38
|
+
private route;
|
|
39
|
+
private sessionService;
|
|
40
|
+
private modalService;
|
|
41
|
+
private confirmDialog;
|
|
42
|
+
/**
|
|
43
|
+
* Config vía @Input (object-first). Si no se pasa, se cae al route data
|
|
44
|
+
* `securityConfig` (poblado por `provideValtechSecurityRoutes`).
|
|
45
|
+
* `resolvedConfig` mergea con los defaults — `@Input` gana sobre route data.
|
|
46
|
+
*/
|
|
47
|
+
config?: SecurityViewConfig;
|
|
48
|
+
readonly resolvedConfig: import("@angular/core").Signal<Required<Omit<SecurityViewConfig, "onMfaCompleted">> & Pick<SecurityViewConfig, "onMfaCompleted">>;
|
|
49
|
+
/** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
|
|
50
|
+
private get ns();
|
|
51
|
+
/**
|
|
52
|
+
* Lista de dispositivos del user. No se renderiza — solo alimenta el modal
|
|
53
|
+
* de confirmación de inicio de sesión (`handleActionTokenFromUrl`) para
|
|
54
|
+
* resolver un label legible desde el `targetId` del token.
|
|
55
|
+
*/
|
|
56
|
+
protected devices: import("@angular/core").WritableSignal<DeviceInfo[]>;
|
|
57
|
+
readonly sessions: import("@angular/core").WritableSignal<SessionInfo[]>;
|
|
58
|
+
readonly sessionsLoading: import("@angular/core").WritableSignal<boolean>;
|
|
59
|
+
readonly isChangeEmailModalOpen: import("@angular/core").WritableSignal<boolean>;
|
|
60
|
+
readonly isChangePasswordModalOpen: import("@angular/core").WritableSignal<boolean>;
|
|
61
|
+
readonly isMfaModalOpen: import("@angular/core").WritableSignal<boolean>;
|
|
62
|
+
/** Código MFA del deep-link `/verify` — pre-carga el modal en confirmación. */
|
|
63
|
+
readonly mfaPrefillCode: import("@angular/core").WritableSignal<string>;
|
|
64
|
+
readonly pageTitle: import("@angular/core").Signal<string>;
|
|
65
|
+
readonly pageDescription: import("@angular/core").Signal<string>;
|
|
66
|
+
readonly quickActionsTitle: import("@angular/core").Signal<string>;
|
|
67
|
+
readonly policiesTitle: import("@angular/core").Signal<string>;
|
|
68
|
+
readonly hasActionCards: import("@angular/core").Signal<boolean>;
|
|
69
|
+
readonly actionCards: import("@angular/core").Signal<ActionCardMetadata[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Fuente única de links legales del producto. Se resuelven vía
|
|
72
|
+
* `LegalLinkService` — apps satélite apuntan al main site, el main site los
|
|
73
|
+
* deja relativos.
|
|
74
|
+
*/
|
|
75
|
+
readonly policyLinksProps: import("@angular/core").Signal<PageLinksMetadata>;
|
|
76
|
+
readonly sessionsTitle: import("@angular/core").Signal<string>;
|
|
77
|
+
readonly sessionsEmptyLabel: import("@angular/core").Signal<string>;
|
|
78
|
+
readonly sessionsThis: import("@angular/core").Signal<string>;
|
|
79
|
+
readonly hasOtherSessions: import("@angular/core").Signal<boolean>;
|
|
80
|
+
/** Sesiones ordenadas: current primero, resto por createdAt desc. */
|
|
81
|
+
readonly sortedSessions: import("@angular/core").Signal<SessionInfo[]>;
|
|
82
|
+
/** Limit de sesiones mostradas inline. Si total > limit, "Ver todas" abre modal. */
|
|
83
|
+
private readonly VISIBLE_LIMIT;
|
|
84
|
+
readonly visibleSessions: import("@angular/core").Signal<SessionInfo[]>;
|
|
85
|
+
readonly hasMoreSessions: import("@angular/core").Signal<boolean>;
|
|
86
|
+
/** Titulo con count: "Sesiones activas (4)". Sin count si N=0. */
|
|
87
|
+
readonly sessionsTitleWithCount: import("@angular/core").Signal<string>;
|
|
88
|
+
readonly revokeOneButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
|
|
89
|
+
readonly viewAllButtonProps: import("@angular/core").Signal<Partial<ButtonMetadata>>;
|
|
90
|
+
/** Action-header de Sesiones: title + count + boton "Cerrar todas las demas". */
|
|
91
|
+
readonly sessionsHeader: import("@angular/core").Signal<ActionHeaderMetadata>;
|
|
92
|
+
constructor();
|
|
93
|
+
/**
|
|
94
|
+
* Llega vía link del email de "nuevo acceso" (`?token=...`). Valida el token
|
|
95
|
+
* (sin ejecutar) y levanta el modal de confirmación. El bloqueo solo se
|
|
96
|
+
* ejecuta si el user confirma "no fui yo" dentro del modal.
|
|
97
|
+
*/
|
|
98
|
+
private handleActionTokenFromUrl;
|
|
99
|
+
private toastTokenInvalid;
|
|
100
|
+
loadDevices(): Promise<void>;
|
|
101
|
+
onActionClick(action: ActionCardMetadata): void;
|
|
102
|
+
onMfaModalDismissed(): void;
|
|
103
|
+
/**
|
|
104
|
+
* El user llegó vía link del email, confirmó MFA en el modal. Cerramos el
|
|
105
|
+
* modal y, si hay hook `onMfaCompleted`, lo invocamos; si no, navegamos al
|
|
106
|
+
* `homeRoute` configurado — quedarse en Settings → Security daría la
|
|
107
|
+
* sensación de "tarea inconclusa" cuando el flow ya terminó.
|
|
108
|
+
*/
|
|
109
|
+
onMfaEnabledViaDeeplink(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Deep-link `/verify?...&verify-code=` → redirige a esta vista con `?mfaCode=`.
|
|
112
|
+
* Abre el modal MFA con el código pre-cargado en el paso de confirmación.
|
|
113
|
+
*/
|
|
114
|
+
private handleMfaCodeFromUrl;
|
|
115
|
+
protected describeDevice(d: DeviceInfo): string;
|
|
116
|
+
protected formatDate(iso?: string): string;
|
|
117
|
+
private toastOk;
|
|
118
|
+
/** Icono según device: phone si UA mobile, sino laptop. */
|
|
119
|
+
deviceIcon(s: SessionInfo): string;
|
|
120
|
+
formatSessionMeta(s: SessionInfo): string;
|
|
121
|
+
onRevokeOne(sessionId: string): Promise<void>;
|
|
122
|
+
onRevokeAll(): Promise<void>;
|
|
123
|
+
/** Abre modal con la lista completa. Cada revoke pasa por `onRevoke`. */
|
|
124
|
+
openSessionsModal(): Promise<void>;
|
|
125
|
+
private loadSessions;
|
|
126
|
+
/** Lee del namespace configurado. */
|
|
127
|
+
protected tt(key: string): string;
|
|
128
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SecurityViewComponent, never>;
|
|
129
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SecurityViewComponent, "val-security-view", never, { "config": { "alias": "config"; "required": false; }; }, {}, never, never, true, never>;
|
|
130
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LanguagesContent } from '../../../services/i18n/types';
|
|
2
|
+
/**
|
|
3
|
+
* Defaults i18n (es/en) embebidos en `val-security-view`. Auto-registrados en el
|
|
4
|
+
* constructor del componente si el consumer no proveyó el namespace
|
|
5
|
+
* (`Settings.Security` por default). Garantiza que nunca haya una key faltante
|
|
6
|
+
* evaluada por cada change-detection (ver nota en valtech-components/CLAUDE.md
|
|
7
|
+
* sobre el storm de CD con `val-debug-console`). El consumer puede override
|
|
8
|
+
* registrando el mismo namespace antes de que el componente monte.
|
|
9
|
+
*
|
|
10
|
+
* SOLO incluye las keys que la vista realmente usa.
|
|
11
|
+
*/
|
|
12
|
+
export declare const SECURITY_VIEW_I18N: LanguagesContent;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Routes } from '@angular/router';
|
|
2
|
+
import { SecurityViewConfig } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Helper para montar la vista Seguridad (`val-security-view`) como ruta en una
|
|
5
|
+
* app del factory. El `config` se pasa por route `data` (`securityConfig`) 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
|
+
* ...provideValtechSecurityRoutes(),
|
|
13
|
+
* { path: 'preferences', loadComponent: () => ... },
|
|
14
|
+
* ];
|
|
15
|
+
*
|
|
16
|
+
* // con config acotada:
|
|
17
|
+
* ...provideValtechSecurityRoutes({ config: { showPolicies: false } }),
|
|
18
|
+
* ...provideValtechSecurityRoutes({ config: { homeRoute: '/app/dashboard' } }),
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function provideValtechSecurityRoutes(opts?: {
|
|
22
|
+
path?: string;
|
|
23
|
+
config?: SecurityViewConfig;
|
|
24
|
+
}): Routes;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuración acotada de `val-security-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 (sesiones,
|
|
8
|
+
* action-cards de cambiar contraseña / email / MFA, políticas legales).
|
|
9
|
+
* - **branding** — `i18nNamespace` para resolver los textos (default
|
|
10
|
+
* `'Settings.Security'`).
|
|
11
|
+
* - **comportamiento / callbacks** — manejo de deep-links del email
|
|
12
|
+
* (`?token`/`?action`/`?mfaCode`), ruta de "home" tras completar MFA y un
|
|
13
|
+
* hook opcional `onMfaCompleted`.
|
|
14
|
+
*/
|
|
15
|
+
export interface SecurityViewConfig {
|
|
16
|
+
/** Muestra la sección de sesiones activas. Default `true`. */
|
|
17
|
+
showSessions?: boolean;
|
|
18
|
+
/** Incluye la action-card "Cambiar contraseña". Default `true`. */
|
|
19
|
+
showChangePassword?: boolean;
|
|
20
|
+
/** Incluye la action-card "Cambiar email". Default `true`. */
|
|
21
|
+
showChangeEmail?: boolean;
|
|
22
|
+
/** Incluye la action-card "Autenticación de dos pasos (MFA)". Default `true`. */
|
|
23
|
+
showMfa?: boolean;
|
|
24
|
+
/** Muestra la sección de políticas legales relacionadas. Default `true`. */
|
|
25
|
+
showPolicies?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Namespace i18n con el que la vista resuelve sus textos.
|
|
28
|
+
* Default `'Settings.Security'`.
|
|
29
|
+
*/
|
|
30
|
+
i18nNamespace?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Habilita el manejo de los deep-links del email
|
|
33
|
+
* (`?token`/`?action`/`?mfaCode`). Default `true`. Requiere que la vista esté
|
|
34
|
+
* montada como ruta (hay `ActivatedRoute`); en modo embebido sin ruta es no-op.
|
|
35
|
+
*/
|
|
36
|
+
handleDeepLinks?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Ruta a la que navegar tras completar MFA vía deep-link. Default `'/app/home'`.
|
|
39
|
+
* Ignorada si se provee `onMfaCompleted`.
|
|
40
|
+
*/
|
|
41
|
+
homeRoute?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Hook invocado cuando el usuario completa MFA vía deep-link. Si se provee, se
|
|
44
|
+
* llama **en lugar** de navegar a `homeRoute`. Útil para apps que quieran
|
|
45
|
+
* decidir el destino post-MFA.
|
|
46
|
+
*/
|
|
47
|
+
onMfaCompleted?: () => void;
|
|
48
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ButtonMetadata } from '../../types';
|
|
2
|
+
import { SessionInfo } from '../../../services/auth/types';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* `val-session-list-modal` — modal de "Ver todas las sesiones activas". Organism
|
|
6
|
+
* compartido entre la vista Seguridad y la vista Cuenta del factory.
|
|
7
|
+
*
|
|
8
|
+
* Render reusa el mismo markup de la sección de sesiones inline (mismas clases
|
|
9
|
+
* CSS) pero sin truncar la lista.
|
|
10
|
+
*
|
|
11
|
+
* Inputs (vienen de `componentProps` del ModalService):
|
|
12
|
+
* - `sessions` — snapshot inicial (mostrado al abrir)
|
|
13
|
+
* - `thisLabel` / `revokeLabel` — i18n strings ya resueltas
|
|
14
|
+
* - `onRevoke` — callback async que el parent ejecuta contra el backend; debe
|
|
15
|
+
* retornar la lista actualizada para que el modal refresque en sitio.
|
|
16
|
+
*
|
|
17
|
+
* `@Output` events NO funcionan con `modalController.create()` — por eso usamos
|
|
18
|
+
* callback pasado por props + `_modalRef` para dismiss desde dentro.
|
|
19
|
+
*
|
|
20
|
+
* Header canónico (Regla #5): sin `ion-title`, botón Cerrar texto en `slot=end`,
|
|
21
|
+
* título en el body con `val-display`.
|
|
22
|
+
*/
|
|
23
|
+
export declare class SessionListModalComponent {
|
|
24
|
+
/** Snapshot inicial — el modal mantiene su propia copia y la refresca tras revoke. */
|
|
25
|
+
set sessions(value: SessionInfo[]);
|
|
26
|
+
/** Título del modal (ya traducido). */
|
|
27
|
+
title: string;
|
|
28
|
+
/** Label del botón cerrar del header (ya traducido). */
|
|
29
|
+
closeLabel: string;
|
|
30
|
+
/** Label "Esta sesión" (en idioma activo). */
|
|
31
|
+
thisLabel: string;
|
|
32
|
+
/** Label del botón revoke individual. */
|
|
33
|
+
revokeLabel: string;
|
|
34
|
+
/**
|
|
35
|
+
* Callback que ejecuta el revoke contra el backend y retorna la lista
|
|
36
|
+
* actualizada. Pasado por `componentProps` del ModalService.
|
|
37
|
+
*/
|
|
38
|
+
onRevoke?: (sessionId: string) => Promise<SessionInfo[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Inyectado por `ModalService.open` — referencia para cerrar desde dentro.
|
|
41
|
+
* Cualquier componente abierto vía el service recibe este objeto en
|
|
42
|
+
* `componentProps`.
|
|
43
|
+
*/
|
|
44
|
+
_modalRef?: {
|
|
45
|
+
dismiss: (data?: unknown, role?: string) => void;
|
|
46
|
+
};
|
|
47
|
+
close(): void;
|
|
48
|
+
/** Lista local mutable — refrescada después de cada revoke confirmado. */
|
|
49
|
+
protected readonly sessionsLocal: import("@angular/core").WritableSignal<SessionInfo[]>;
|
|
50
|
+
handleRevoke(sessionId: string): Promise<void>;
|
|
51
|
+
get revokeBtn(): Partial<ButtonMetadata>;
|
|
52
|
+
deviceIcon(s: SessionInfo): string;
|
|
53
|
+
formatMeta(s: SessionInfo): string;
|
|
54
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<SessionListModalComponent, never>;
|
|
55
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SessionListModalComponent, "val-session-list-modal", never, { "sessions": { "alias": "sessions"; "required": false; }; "title": { "alias": "title"; "required": false; }; "closeLabel": { "alias": "closeLabel"; "required": false; }; "thisLabel": { "alias": "thisLabel"; "required": false; }; "revokeLabel": { "alias": "revokeLabel"; "required": false; }; "onRevoke": { "alias": "onRevoke"; "required": false; }; "_modalRef": { "alias": "_modalRef"; "required": false; }; }, {}, never, never, true, never>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SessionInfo } from '../../../services/auth/types';
|
|
2
|
+
/**
|
|
3
|
+
* Props de `val-session-list-modal` (organism compartido — lo reusan la vista
|
|
4
|
+
* Seguridad y la vista Cuenta).
|
|
5
|
+
*
|
|
6
|
+
* Se pasan por `componentProps` del `ModalService.openSheet(...)`. Son escalares
|
|
7
|
+
* + un callback (`onRevoke`) — NO `@Output`, porque los eventos no funcionan con
|
|
8
|
+
* `modalController.create()`. El componente es **agnóstico a i18n**: recibe los
|
|
9
|
+
* labels ya traducidos.
|
|
10
|
+
*/
|
|
11
|
+
export interface SessionListModalProps {
|
|
12
|
+
/** Snapshot inicial de sesiones — el modal mantiene su copia y la refresca tras revoke. */
|
|
13
|
+
sessions: SessionInfo[];
|
|
14
|
+
/** Título del modal (ya traducido). */
|
|
15
|
+
title: string;
|
|
16
|
+
/** Label del botón cerrar del header (ya traducido). */
|
|
17
|
+
closeLabel: string;
|
|
18
|
+
/** Label "Esta sesión" (en idioma activo). */
|
|
19
|
+
thisLabel: string;
|
|
20
|
+
/** Label del botón revoke individual. */
|
|
21
|
+
revokeLabel: string;
|
|
22
|
+
/**
|
|
23
|
+
* Callback que ejecuta el revoke contra el backend y retorna la lista
|
|
24
|
+
* actualizada para refrescar el modal en sitio.
|
|
25
|
+
*/
|
|
26
|
+
onRevoke?: (sessionId: string) => Promise<SessionInfo[]>;
|
|
27
|
+
}
|
package/lib/version.d.ts
CHANGED
package/package.json
CHANGED
package/public-api.d.ts
CHANGED
|
@@ -272,6 +272,12 @@ export * from './lib/components/organisms/settings-hub/settings-hub.component';
|
|
|
272
272
|
export * from './lib/components/organisms/settings-hub/types';
|
|
273
273
|
export * from './lib/components/organisms/settings-hub/settings-sections';
|
|
274
274
|
export * from './lib/components/organisms/settings-hub/settings.routes';
|
|
275
|
+
export * from './lib/components/organisms/security-view/security-view.component';
|
|
276
|
+
export * from './lib/components/organisms/security-view/types';
|
|
277
|
+
export * from './lib/components/organisms/security-view/security.routes';
|
|
278
|
+
export * from './lib/components/organisms/login-attempt-modal/login-attempt-modal.component';
|
|
279
|
+
export * from './lib/components/organisms/session-list-modal/session-list-modal.component';
|
|
280
|
+
export * from './lib/components/organisms/session-list-modal/types';
|
|
275
281
|
export * from './lib/components/organisms/skeleton-layout/skeleton-layout.component';
|
|
276
282
|
export * from './lib/components/organisms/skeleton-layout/types';
|
|
277
283
|
export * from './lib/components/organisms/faq/faq.component';
|