valtech-components 4.0.219 → 4.0.221

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 (46) hide show
  1. package/esm2022/lib/components/molecules/chat-input/chat-input.component.mjs +157 -0
  2. package/esm2022/lib/components/molecules/chat-input/types.mjs +2 -0
  3. package/esm2022/lib/components/molecules/message-bubble/message-bubble.component.mjs +244 -0
  4. package/esm2022/lib/components/molecules/message-bubble/types.mjs +2 -0
  5. package/esm2022/lib/components/molecules/typing-indicator/typing-indicator.component.mjs +76 -0
  6. package/esm2022/lib/components/organisms/chat-window/chat-window.component.mjs +246 -0
  7. package/esm2022/lib/components/organisms/chat-window/types.mjs +2 -0
  8. package/esm2022/lib/components/organisms/thread-panel/thread-panel.component.mjs +211 -0
  9. package/esm2022/lib/services/chat/config.mjs +35 -0
  10. package/esm2022/lib/services/chat/conversation.service.mjs +274 -0
  11. package/esm2022/lib/services/chat/types.mjs +10 -0
  12. package/esm2022/lib/services/entity-feed/entity-feed.service.mjs +103 -0
  13. package/esm2022/lib/services/entity-feed/index.mjs +2 -0
  14. package/esm2022/lib/services/entity-feed/types.mjs +2 -0
  15. package/esm2022/lib/services/i18n/default-content.mjs +65 -1
  16. package/esm2022/lib/version.mjs +2 -2
  17. package/esm2022/public-api.mjs +16 -1
  18. package/fesm2022/valtech-components.mjs +1370 -3
  19. package/fesm2022/valtech-components.mjs.map +1 -1
  20. package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +2 -2
  21. package/lib/components/atoms/text/text.component.d.ts +1 -1
  22. package/lib/components/atoms/user-avatar/user-avatar.component.d.ts +1 -1
  23. package/lib/components/molecules/chat-input/chat-input.component.d.ts +38 -0
  24. package/lib/components/molecules/chat-input/types.d.ts +20 -0
  25. package/lib/components/molecules/cta-card/cta-card.component.d.ts +1 -1
  26. package/lib/components/molecules/features-list/features-list.component.d.ts +1 -1
  27. package/lib/components/molecules/load-more/load-more.component.d.ts +1 -1
  28. package/lib/components/molecules/message-bubble/message-bubble.component.d.ts +40 -0
  29. package/lib/components/molecules/message-bubble/types.d.ts +64 -0
  30. package/lib/components/molecules/metric-card/metric-card.component.d.ts +1 -1
  31. package/lib/components/molecules/typing-indicator/typing-indicator.component.d.ts +19 -0
  32. package/lib/components/organisms/article/article.component.d.ts +7 -7
  33. package/lib/components/organisms/auth-cta/auth-cta.component.d.ts +1 -1
  34. package/lib/components/organisms/chat-window/chat-window.component.d.ts +63 -0
  35. package/lib/components/organisms/chat-window/types.d.ts +36 -0
  36. package/lib/components/organisms/landing-steps/landing-steps.component.d.ts +1 -1
  37. package/lib/components/organisms/thread-panel/thread-panel.component.d.ts +55 -0
  38. package/lib/services/chat/config.d.ts +37 -0
  39. package/lib/services/chat/conversation.service.d.ts +147 -0
  40. package/lib/services/chat/types.d.ts +145 -0
  41. package/lib/services/entity-feed/entity-feed.service.d.ts +71 -0
  42. package/lib/services/entity-feed/index.d.ts +2 -0
  43. package/lib/services/entity-feed/types.d.ts +26 -0
  44. package/lib/version.d.ts +1 -1
  45. package/package.json +2 -2
  46. package/public-api.d.ts +13 -0
@@ -0,0 +1,147 @@
1
+ import { Observable } from 'rxjs';
2
+ import { Conversation, ConversationType, CreateConversationRequest, ListConversationsResponse, Message, UpdateConversationRequest } from './types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * ConversationService
6
+ *
7
+ * Gestiona conversaciones y mensajes del chat.
8
+ *
9
+ * Dos capas:
10
+ * - HTTP (via backend /v2/chat/*): operaciones de escritura y consulta.
11
+ * - Firestore real-time (directa): escucha mensajes y estado de escritura.
12
+ *
13
+ * Paths Firestore:
14
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/messages/{msgId}
15
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/typing/{userId}
16
+ *
17
+ * @example
18
+ * // Enviar y escuchar mensajes
19
+ * const svc = inject(ConversationService);
20
+ *
21
+ * // Enviar (HTTP)
22
+ * svc.sendMessage(convId, 'Hola!').subscribe();
23
+ *
24
+ * // Escuchar en tiempo real (Firestore)
25
+ * svc.watchMessages(convId, orgId, appId).subscribe(msgs => this.messages.set(msgs));
26
+ */
27
+ export declare class ConversationService {
28
+ private config;
29
+ private http;
30
+ private firestoreService;
31
+ private firestore;
32
+ constructor();
33
+ private get baseUrl();
34
+ /**
35
+ * Crea una nueva conversacion.
36
+ */
37
+ createConversation(req: CreateConversationRequest): Observable<Conversation>;
38
+ /**
39
+ * Obtiene o crea una conversacion asociada a una entidad (post, request, etc.).
40
+ * Usa el patron upsert del backend: si ya existe una conversacion para esa entidad,
41
+ * la devuelve; si no, la crea.
42
+ */
43
+ getOrCreateForEntity(entityType: string, entityId: string, type?: ConversationType): Observable<Conversation>;
44
+ /**
45
+ * Lista las conversaciones del usuario autenticado.
46
+ */
47
+ listConversations(cursor?: string): Observable<ListConversationsResponse>;
48
+ /**
49
+ * Obtiene una conversacion por ID.
50
+ */
51
+ getConversation(convId: string): Observable<Conversation>;
52
+ /**
53
+ * Actualiza el titulo o estado de una conversacion.
54
+ */
55
+ updateConversation(convId: string, req: UpdateConversationRequest): Observable<Conversation>;
56
+ /**
57
+ * Abre una conversacion cerrada.
58
+ */
59
+ openConversation(convId: string): Observable<void>;
60
+ /**
61
+ * Cierra una conversacion.
62
+ */
63
+ closeConversation(convId: string): Observable<void>;
64
+ /**
65
+ * Agrega un participante a la conversacion.
66
+ */
67
+ addParticipant(convId: string, userId: string): Observable<void>;
68
+ /**
69
+ * Elimina un participante de la conversacion.
70
+ */
71
+ removeParticipant(convId: string, userId: string): Observable<void>;
72
+ /**
73
+ * Envia un mensaje a una conversacion.
74
+ */
75
+ sendMessage(convId: string, body: string): Observable<Message>;
76
+ /**
77
+ * Elimina (marca como eliminado) un mensaje.
78
+ */
79
+ deleteMessage(convId: string, msgId: string): Observable<void>;
80
+ /**
81
+ * Construye el path base para los datos de una conversacion.
82
+ * Nota: usamos el path completo con skipPrefix porque el path ya incluye
83
+ * apps/{appId}/orgs/{orgId} que el FirestoreService prefijaria de nuevo.
84
+ * En cambio armamos el path como sub-coleccion directamente.
85
+ */
86
+ private convMessagesPath;
87
+ private convTypingPath;
88
+ /**
89
+ * Escucha los mensajes de una conversacion en tiempo real.
90
+ *
91
+ * @param convId - ID de la conversacion
92
+ * @param orgId - ID de la organizacion
93
+ * @param appId - ID de la aplicacion
94
+ * @param limit - Cantidad maxima de mensajes a cargar (default 50)
95
+ */
96
+ watchMessages(convId: string, orgId: string, appId: string, limit?: number): Observable<Message[]>;
97
+ /**
98
+ * Escucha los usuarios que estan escribiendo en una conversacion.
99
+ * Devuelve un array de displayNames.
100
+ *
101
+ * @param convId - ID de la conversacion
102
+ * @param orgId - ID de la organizacion
103
+ * @param appId - ID de la aplicacion
104
+ */
105
+ watchTyping(convId: string, orgId: string, appId: string): Observable<string[]>;
106
+ /**
107
+ * Registra que el usuario actual esta escribiendo.
108
+ * El documento se sobreescribe para actualizar el timestamp.
109
+ * Debe llamarse con un TTL/cleanup (ver stopTyping).
110
+ *
111
+ * @param convId - ID de la conversacion
112
+ * @param orgId - ID de la organizacion
113
+ * @param appId - ID de la aplicacion
114
+ * @param displayName - Nombre visible del usuario
115
+ */
116
+ startTyping(convId: string, orgId: string, appId: string, displayName: string): void;
117
+ /**
118
+ * Elimina el documento de "escribiendo" del usuario actual.
119
+ *
120
+ * @param convId - ID de la conversacion
121
+ * @param orgId - ID de la organizacion
122
+ * @param appId - ID de la aplicacion
123
+ */
124
+ stopTyping(convId: string, orgId: string, appId: string): void;
125
+ /**
126
+ * Marca un mensaje como leido por el usuario actual.
127
+ * Escribe directamente en Firestore sin pasar por el backend.
128
+ *
129
+ * @param convId - ID de la conversacion
130
+ * @param msgId - ID del ultimo mensaje leido
131
+ * @param orgId - ID de la organizacion
132
+ * @param appId - ID de la aplicacion
133
+ */
134
+ markRead(convId: string, msgId: string, orgId: string, appId: string): void;
135
+ /**
136
+ * Importa ABS_PATH_SENTINEL de forma lazy para evitar dependencias circulares.
137
+ */
138
+ private getAbsPathSentinel;
139
+ /**
140
+ * Obtiene el userId del usuario actual desde sessionStorage / localStorage
141
+ * como fallback no-DI para el contexto de escritura de Firestore.
142
+ * En prod, el AuthService actualiza el userId en el contexto de la app.
143
+ */
144
+ private getCurrentUserId;
145
+ static ɵfac: i0.ɵɵFactoryDeclaration<ConversationService, never>;
146
+ static ɵprov: i0.ɵɵInjectableDeclaration<ConversationService>;
147
+ }
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Chat Service Types
3
+ *
4
+ * Tipos compartidos para el sistema de chat en tiempo real.
5
+ * Firestore paths:
6
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/messages/{msgId}
7
+ * /apps/{appId}/orgs/{orgId}/conversations/{convId}/typing/{userId}
8
+ */
9
+ import { FirestoreDocument } from '../firebase/types';
10
+ /** Tipo de conversacion. */
11
+ export type ConversationType = 'direct' | 'group' | 'entity';
12
+ /** Estado de una conversacion. */
13
+ export type ConversationStatus = 'open' | 'closed';
14
+ /** Participante de una conversacion. */
15
+ export interface ConversationParticipant {
16
+ /** ID del usuario. */
17
+ userId: string;
18
+ /** Nombre visible del usuario. */
19
+ displayName: string;
20
+ /** URL del avatar del usuario (opcional). */
21
+ avatarUrl?: string;
22
+ /** Fecha en que se unio a la conversacion. */
23
+ joinedAt: Date;
24
+ /** Ultimo mensaje leido por este participante. */
25
+ lastReadMsgId?: string;
26
+ }
27
+ /** Documento de conversacion en Firestore. */
28
+ export interface Conversation extends FirestoreDocument {
29
+ /** Tipo de conversacion. */
30
+ type: ConversationType;
31
+ /** Estado de la conversacion. */
32
+ status: ConversationStatus;
33
+ /** Participantes. */
34
+ participants: ConversationParticipant[];
35
+ /** Tipo de entidad asociada (para tipo entity). */
36
+ entityType?: string;
37
+ /** ID de la entidad asociada. */
38
+ entityId?: string;
39
+ /** Titulo de la conversacion (para grupos). */
40
+ title?: string;
41
+ /** ID del ultimo mensaje. */
42
+ lastMsgId?: string;
43
+ /** Texto del ultimo mensaje (preview). */
44
+ lastMsgBody?: string;
45
+ /** Fecha del ultimo mensaje. */
46
+ lastMsgAt?: Date;
47
+ /** Conteo de mensajes no leidos por userId. */
48
+ unreadCount?: Record<string, number>;
49
+ }
50
+ /** Tipo de mensaje. */
51
+ export type MessageType = 'text' | 'image' | 'file' | 'system';
52
+ /** Estado de envio del mensaje. */
53
+ export type MessageStatus = 'sending' | 'sent' | 'failed';
54
+ /** Archivo adjunto en un mensaje. */
55
+ export interface MessageAttachment {
56
+ /** Nombre del archivo. */
57
+ name: string;
58
+ /** URL de descarga. */
59
+ url: string;
60
+ /** Tipo MIME. */
61
+ mimeType: string;
62
+ /** Tamano en bytes. */
63
+ size?: number;
64
+ }
65
+ /** Reaccion a un mensaje. */
66
+ export interface MessageReaction {
67
+ /** Token del emoji (ej: 'like', 'heart'). */
68
+ token: string;
69
+ /** Cantidad de usuarios que reaccionaron con este emoji. */
70
+ count: number;
71
+ /** Si el usuario actual tiene activa esta reaccion. */
72
+ active: boolean;
73
+ }
74
+ /** Referencia al mensaje al que se responde. */
75
+ export interface MessageReplyTo {
76
+ /** ID del mensaje original. */
77
+ msgId: string;
78
+ /** Nombre del emisor del mensaje original. */
79
+ senderName: string;
80
+ /** Texto del mensaje original (preview). */
81
+ body: string;
82
+ }
83
+ /** Documento de mensaje en Firestore. */
84
+ export interface Message extends FirestoreDocument {
85
+ /** ID del emisor. */
86
+ senderId: string;
87
+ /** Nombre visible del emisor. */
88
+ senderName: string;
89
+ /** URL del avatar del emisor (opcional). */
90
+ senderAvatar?: string;
91
+ /** Cuerpo del mensaje. */
92
+ body: string;
93
+ /** Tipo de mensaje. */
94
+ type: MessageType;
95
+ /** Fecha de creacion del mensaje. */
96
+ createdAt: Date;
97
+ /** Si el mensaje fue eliminado. */
98
+ isDeleted?: boolean;
99
+ /** Si el mensaje fue editado. */
100
+ isEdited?: boolean;
101
+ /** Mensaje al que se responde. */
102
+ replyTo?: MessageReplyTo;
103
+ /** Archivos adjuntos. */
104
+ attachments?: MessageAttachment[];
105
+ /** Reacciones del mensaje. */
106
+ reactions?: MessageReaction[];
107
+ /** Estado de envio (para mensajes optimistas del lado del cliente). */
108
+ status?: MessageStatus;
109
+ }
110
+ /** Documento de "escribiendo" en Firestore. */
111
+ export interface TypingDocument extends FirestoreDocument {
112
+ /** Nombre visible del usuario que esta escribiendo. */
113
+ displayName: string;
114
+ /** Timestamp de la ultima actualizacion. */
115
+ updatedAt: Date;
116
+ }
117
+ /** Request para crear una conversacion. */
118
+ export interface CreateConversationRequest {
119
+ /** Tipo de conversacion. */
120
+ type: ConversationType;
121
+ /** IDs de los participantes iniciales. */
122
+ participantIds?: string[];
123
+ /** Para tipo entity: tipo de la entidad. */
124
+ entityType?: string;
125
+ /** Para tipo entity: ID de la entidad. */
126
+ entityId?: string;
127
+ /** Titulo (para grupos). */
128
+ title?: string;
129
+ }
130
+ /** Request para actualizar una conversacion. */
131
+ export interface UpdateConversationRequest {
132
+ /** Nuevo titulo (opcional). */
133
+ title?: string;
134
+ /** Nuevo estado (opcional). */
135
+ status?: ConversationStatus;
136
+ }
137
+ /** Response de listado de conversaciones. */
138
+ export interface ListConversationsResponse {
139
+ /** Lista de conversaciones. */
140
+ conversations: Conversation[];
141
+ /** Cursor para paginacion. */
142
+ nextCursor?: string;
143
+ /** Si hay mas paginas. */
144
+ hasMore: boolean;
145
+ }
@@ -0,0 +1,71 @@
1
+ import { Observable } from 'rxjs';
2
+ import { EntityFeedItem, EntityFeedItemWithReaction } from './types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * EntityFeedService — capa de lectura Firestore para entidades proyectables.
6
+ *
7
+ * Soporta cualquier tipo de entidad (posts, articles, adoptions, reels...)
8
+ * siguiendo el esquema de paths:
9
+ * - Entidades: apps/{appId}/orgs/{orgId}/{entityType}s/{entityId}
10
+ * - Reacciones del usuario: apps/{appId}/users/{uid}/reactions/{entityType}_{entityId}
11
+ *
12
+ * FirestoreService auto-prefija los paths con apps/{appId}/.
13
+ *
14
+ * @example
15
+ * const feed = inject(EntityFeedService);
16
+ *
17
+ * // Solo entidades
18
+ * feed.watchEntities<Post>('org_x', 'post').subscribe(posts => ...);
19
+ *
20
+ * // Feed con reaccion del viewer incluida
21
+ * feed.watchFeed<Post>('org_x', 'post').subscribe(items => {
22
+ * items.forEach(item => console.log(item.viewerHasReacted, item.viewerToken));
23
+ * });
24
+ */
25
+ export declare class EntityFeedService {
26
+ private fs;
27
+ private auth;
28
+ /**
29
+ * Suscripcion en tiempo real a entidades publicadas de un tipo dado.
30
+ *
31
+ * Coleccion: orgs/{orgId}/{entityType}s
32
+ * Auto-prefijada a: apps/{appId}/orgs/{orgId}/{entityType}s
33
+ *
34
+ * Filtra por status === 'published', ordena por publishedAt desc.
35
+ *
36
+ * @param orgId - ID de la organizacion
37
+ * @param entityType - Tipo de entidad en singular (ej. 'post', 'article')
38
+ * @param options - Opciones opcionales (limit, default 20)
39
+ */
40
+ watchEntities<T extends EntityFeedItem>(orgId: string, entityType: string, options?: {
41
+ limit?: number;
42
+ }): Observable<T[]>;
43
+ /**
44
+ * Suscripcion en tiempo real a las reacciones del usuario actual para un tipo de entidad.
45
+ *
46
+ * Coleccion: users/{uid}/reactions
47
+ * Auto-prefijada a: apps/{appId}/users/{uid}/reactions
48
+ *
49
+ * Retorna un Map<entityId, token> para lookup O(1) al combinar con el feed.
50
+ * Si no hay usuario autenticado, retorna un Map vacio.
51
+ *
52
+ * @param entityType - Tipo de entidad a filtrar (ej. 'post', 'article')
53
+ */
54
+ watchMyReactions(entityType: string): Observable<Map<string, string>>;
55
+ /**
56
+ * Combina watchEntities + watchMyReactions en un unico stream.
57
+ *
58
+ * Cada item del feed incluye viewerToken y viewerHasReacted, listos para
59
+ * renderizar el estado de reaccion del usuario actual sin logica adicional
60
+ * en la pagina.
61
+ *
62
+ * @param orgId - ID de la organizacion
63
+ * @param entityType - Tipo de entidad en singular (ej. 'post', 'article')
64
+ * @param options - Opciones opcionales (limit, default 20)
65
+ */
66
+ watchFeed<T extends EntityFeedItem>(orgId: string, entityType: string, options?: {
67
+ limit?: number;
68
+ }): Observable<EntityFeedItemWithReaction<T>[]>;
69
+ static ɵfac: i0.ɵɵFactoryDeclaration<EntityFeedService, never>;
70
+ static ɵprov: i0.ɵɵInjectableDeclaration<EntityFeedService>;
71
+ }
@@ -0,0 +1,2 @@
1
+ export { EntityFeedService } from './entity-feed.service';
2
+ export type { EntityFeedItem, UserReactionDoc, EntityFeedItemWithReaction } from './types';
@@ -0,0 +1,26 @@
1
+ export interface EntityFeedItem {
2
+ id: string;
3
+ entityType: string;
4
+ visibility: 'public' | 'org' | 'private';
5
+ authorId: string;
6
+ authorName: string;
7
+ authorAvatarUrl?: string;
8
+ title?: string;
9
+ excerpt?: string;
10
+ coverImage?: string;
11
+ publishedAt?: Date;
12
+ updatedAt?: Date;
13
+ reactionCounts?: Record<string, number>;
14
+ commentCount?: number;
15
+ }
16
+ export interface UserReactionDoc {
17
+ id: string;
18
+ token: string;
19
+ entityType: string;
20
+ entityId: string;
21
+ createdAt?: Date;
22
+ }
23
+ export type EntityFeedItemWithReaction<T extends EntityFeedItem = EntityFeedItem> = T & {
24
+ viewerToken: string | null;
25
+ viewerHasReacted: boolean;
26
+ };
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 = "4.0.211";
5
+ export declare const VERSION = "4.0.221";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valtech-components",
3
- "version": "4.0.219",
3
+ "version": "4.0.221",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "valtech-firebase-config": "./src/lib/services/firebase/scripts/generate-sw-config.js"
@@ -65,4 +65,4 @@
65
65
  "default": "./fesm2022/valtech-components.mjs"
66
66
  }
67
67
  }
68
- }
68
+ }
package/public-api.d.ts CHANGED
@@ -413,6 +413,7 @@ export * from './lib/components/molecules/request-form/types';
413
413
  export * from './lib/components/molecules/content-reaction/content-reaction.component';
414
414
  export * from './lib/components/molecules/content-reaction/types';
415
415
  export * from './lib/services/reactions/index';
416
+ export * from './lib/services/entity-feed/index';
416
417
  export * from './lib/components/molecules/reaction-bar/reaction-bar.component';
417
418
  export * from './lib/components/molecules/reaction-bar/types';
418
419
  export * from './lib/services/splash-screen';
@@ -469,3 +470,15 @@ export * from './lib/components/organisms/qr-scanner/qr-scanner.component';
469
470
  export * from './lib/components/organisms/qr-scanner/types';
470
471
  export * from './lib/components/organisms/html-viewer-modal/html-viewer-modal.component';
471
472
  export * from './lib/components/molecules/form-field/form-field.component';
473
+ export { ConversationService } from './lib/services/chat/conversation.service';
474
+ export { provideValtechChat, VALTECH_CHAT_CONFIG } from './lib/services/chat/config';
475
+ export type { ValtechChatConfig } from './lib/services/chat/config';
476
+ export * from './lib/services/chat/types';
477
+ export { MessageBubbleComponent } from './lib/components/molecules/message-bubble/message-bubble.component';
478
+ export * from './lib/components/molecules/message-bubble/types';
479
+ export { ChatInputComponent } from './lib/components/molecules/chat-input/chat-input.component';
480
+ export * from './lib/components/molecules/chat-input/types';
481
+ export { TypingIndicatorComponent } from './lib/components/molecules/typing-indicator/typing-indicator.component';
482
+ export { ChatWindowComponent } from './lib/components/organisms/chat-window/chat-window.component';
483
+ export * from './lib/components/organisms/chat-window/types';
484
+ export { ThreadPanelComponent } from './lib/components/organisms/thread-panel/thread-panel.component';