wm-menu 1.6.0 → 1.7.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"wm-menu.js","sources":["ng://wm-menu/lib/wm-menu/model/wm-menu-cuenta.model.ts","ng://wm-menu/lib/wm-menu/services/wm-menu-servicio.service.ts","ng://wm-menu/lib/wm-menu/services/wm-menu-alerta-panico.service.ts","ng://wm-menu/lib/wm-menu/services/wm-menu-fuente-iconos.service.ts","ng://wm-menu/lib/wm-menu/wm-menu.component.ts","ng://wm-menu/lib/wm-menu/asistente-datos/reconocimiento-voz.service.ts","ng://wm-menu/lib/wm-menu/asistente-datos/asistente-datos-api.service.ts","ng://wm-menu/lib/wm-menu/asistente-datos/tabla-export.service.ts","ng://wm-menu/lib/wm-menu/asistente-datos/asistente-datos.component.ts","ng://wm-menu/lib/wm-menu.module.ts","ng://wm-menu/public-api.ts","ng://wm-menu/wm-menu.ts"],"sourcesContent":["export class MenuSecundario {\r\n icono: string;\r\n titulo: string;\r\n hijos: MenuSecundarioHijo[] = [];\r\n}\r\n\r\nexport class MenuSecundarioHijo {\r\n icono: string;\r\n titulo: string;\r\n url: string;\r\n}","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';\r\nimport { map, catchError } from 'rxjs/operators';\r\nimport { throwError, Observable } from 'rxjs';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { MatIconRegistry } from '@angular/material/icon';\r\nimport { MenuPrincipal } from '../model/wm-menu-principal.model';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WmMenuServicioService {\r\n\r\n constructor(private http: HttpClient, private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) { }\r\n\r\n menuApiObtener(url:string, idUsuario: string, token:string, codLogicaParametro = \"\"): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n \r\n let myParams = new HttpParams();\r\n if (codLogicaParametro.length > 0) {\r\n myParams = myParams.append(\"codLogica\", codLogicaParametro);\r\n }\r\n myParams = myParams.append(\"ctrlActivo\", \"true\");\r\n myParams = myParams.append(\"conPadres\", \"true\");\r\n if (idUsuario != null)\r\n myParams = myParams.append(\"idUsuario\", idUsuario.toString());\r\n\r\n return this.http.get(url, { headers, params: myParams }).pipe(\r\n map(resp => {\r\n return resp;\r\n }),\r\n catchError(error => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n\r\n mapearMenu(respApi: any): MenuPrincipal[] {\r\n respApi = respApi.sort((a, b) => a.Posicion > b.Posicion?\"1\":\"-1\");\r\n\r\n for (const key in respApi) {\r\n const element = respApi[key];\r\n if (element.Icono.startsWith(\"http\")) {\r\n var iconSvg = 'wm-icon-menu-' + key;\r\n this.iconRegistry.addSvgIcon(\r\n iconSvg,\r\n this.sanitizer.bypassSecurityTrustResourceUrl(element.Icono));\r\n respApi[key].Icono = iconSvg;\r\n }\r\n }\r\n\r\n return this.obtenerMenu(respApi);\r\n }\r\n\r\n\r\n private obtenerMenu(respApi: any, idMenuPadre?: Number): MenuPrincipal[] {\r\n var menu: MenuPrincipal[] = [];\r\n for (const key in respApi) {\r\n if (respApi[key].IdMenuPadre == idMenuPadre || (!idMenuPadre && respApi[key].IdMenuPadre == null)) {\r\n menu.push({\r\n titulo: respApi[key].IdiomaRecurso,\r\n url: respApi[key].Url,\r\n icono: respApi[key].Icono,\r\n descripcion: respApi[key].Descripcion,\r\n hijos: this.obtenerMenu(respApi, respApi[key].IdMenu)\r\n });\r\n }\r\n }\r\n return menu;\r\n }\r\n\r\n menuIdiomasObtener(url:string, idUsuario: string, token:string): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n\r\n return this.http.get(url).pipe(\r\n map(resp => {\r\n return resp;\r\n }),\r\n catchError(error => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n \r\n almacenamientoApiObtener(url:string, idUsuario: string, token:string): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n \r\n let myParams = new HttpParams();\r\n\r\n if (idUsuario != null)\r\n myParams = myParams.append(\"idUsuario\", idUsuario.toString());\r\n \r\n return this.http.get(url, { headers, params: myParams }).pipe(\r\n map(resp => {\r\n return resp;\r\n }),\r\n catchError(error => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n\r\n // Funciones (permisos) del usuario autenticado, para gatear features del menú como el\r\n // asistente \"Pregúntale a tus datos\" (CodigoLogica === 'WebChatConsultaIA').\r\n funcionesObtener(url: string, token: string): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n\r\n return this.http.get(url, { headers }).pipe(\r\n map(resp => resp),\r\n catchError(error => throwError(error.error))\r\n );\r\n }\r\n}","import { Injectable } from '@angular/core';\r\nimport { JwtHelperService } from '@auth0/angular-jwt';\r\nimport { WmMenuServicioService } from './wm-menu-servicio.service';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WmMenuAlertaPanicoService {\r\n\r\n private intervalId: any;\r\n private alternateTitle = 'Alerta de Pánico Recibida';\r\n private originalTitle: string;\r\n private audio: HTMLAudioElement | null = null;\r\n private isPlaying = false; // Controla si el sonido ya está reproduciéndose\r\n public formulario: any;\r\n private IdsAlertasPanicoActivas: Set<number> = new Set(); // Almacena los IDs de las alertas ya manejadas\r\n private soundTimeout: any = null; // Controla el temporizador del sonido\r\n private rutaAudio: string;\r\n constructor(private wmMenuServicioService: WmMenuServicioService) { }\r\n\r\n private subscription: any;\r\n private isRunning: boolean = false;\r\n\r\n iniciarProceso(\r\n intervalMs: number,\r\n callback: () => void,\r\n urlObtenerParametro: string,\r\n token: string,\r\n rutaAudio: string\r\n ): void {\r\n this.rutaAudio = rutaAudio;\r\n \r\n const iniciarConInteraccion = () => {\r\n this.wmMenuServicioService\r\n .menuApiObtener(urlObtenerParametro, null, token, 'ReporteAlertasPanico')\r\n .subscribe((resp) => {\r\n // validar si el parametro ReporteAlertasPanico esta encendido\r\n if (resp && resp.length > 0 && resp[0].Valor == 1) {\r\n if (this.isRunning) {\r\n return;\r\n }\r\n // Inicializar la variable desde localStorage\r\n const storedIds = localStorage.getItem('ALERTAS_PANICO_ACTIVAS_WM');\r\n this.IdsAlertasPanicoActivas = storedIds ? new Set(JSON.parse(storedIds)) : new Set();\r\n \r\n const ejecutarProceso = () => {\r\n this.isRunning = true;\r\n callback();\r\n setTimeout(() => {\r\n this.isRunning = false;\r\n ejecutarProceso();\r\n }, intervalMs);\r\n };\r\n \r\n ejecutarProceso();\r\n }\r\n });\r\n };\r\n \r\n ['drag', 'click'].forEach(evento => {\r\n document.addEventListener(\r\n evento,\r\n () => {\r\n iniciarConInteraccion();\r\n },\r\n { once: true }\r\n );\r\n });\r\n\r\n }\r\n \r\n\r\n stopProcess(): void {\r\n this.isRunning = false;\r\n if (this.subscription) {\r\n this.subscription.unsubscribe();\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.stopSound();\r\n this.stopFlashingTitle();\r\n }\r\n\r\n playSound(): void {\r\n if (this.isPlaying) return; // Evita reproducir si ya está sonando\r\n\r\n this.isPlaying = true;\r\n if (!this.audio) {\r\n this.audio = new Audio(this.rutaAudio); // Ruta al archivo de sonido\r\n }\r\n\r\n this.audio.loop = true; // Reproducir en bucle\r\n this.audio.play()\r\n .then(() => {\r\n // Detener el sonido después de 10 segundos\r\n this.soundTimeout = setTimeout(() => {\r\n this.stopSound();\r\n }, 10000); // Detener después de 10 segundos\r\n })\r\n .catch(error => {\r\n console.log('Error al reproducir el sonido:', error);\r\n });\r\n }\r\n\r\n stopSound(): void {\r\n if (this.audio) {\r\n this.audio.pause();\r\n this.audio.currentTime = 0; // Reinicia el sonido\r\n }\r\n this.isPlaying = false; // Restablece la bandera\r\n if (this.soundTimeout) {\r\n clearTimeout(this.soundTimeout); // Asegura que el temporizador se borre\r\n this.soundTimeout = null;\r\n }\r\n }\r\n\r\n startFlashingTitle(): void {\r\n let toggle = false;\r\n \r\n // Almacenar el título original si aún no se ha guardado\r\n if (!this.originalTitle) {\r\n this.originalTitle = document.title;\r\n }\r\n \r\n if (!this.intervalId) {\r\n this.intervalId = setInterval(() => {\r\n // Alternar entre el título alternativo y el título original\r\n document.title = toggle ? this.alternateTitle : this.originalTitle;\r\n toggle = !toggle;\r\n }, 1000); // Cambia el título cada segundo\r\n }\r\n }\r\n\r\n stopFlashingTitle(): void {\r\n if (this.intervalId) {\r\n clearInterval(this.intervalId);\r\n this.intervalId = null;\r\n document.title = this.originalTitle; // Restaura a vacío\r\n }\r\n }\r\n\r\n revisarAlertasPendientes(urlObtenerAlertasPanico: string, token: string): void {\r\n const helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(token);\r\n this.wmMenuServicioService\r\n .menuApiObtener(urlObtenerAlertasPanico, decodedToken['id_usuario'], token)\r\n .subscribe((resp) => {\r\n if (resp && resp.length > 0) {\r\n \r\n const alertasIds = resp.map(alerta => alerta.IdAlertaPanico);\r\n\r\n // Eliminar IDs que no están en la respuesta del servicio\r\n this.IdsAlertasPanicoActivas.forEach((id) => {\r\n if (!alertasIds.includes(id)) {\r\n this.IdsAlertasPanicoActivas.delete(id);\r\n }\r\n });\r\n\r\n // Filtrar alertas nuevas\r\n const newAlerts = resp.filter(alerta => !this.IdsAlertasPanicoActivas.has(alerta.IdAlertaPanico));\r\n\r\n // Agregar las nuevas alertas a la lista activa\r\n newAlerts.forEach(alerta => this.IdsAlertasPanicoActivas.add(alerta.IdAlertaPanico));\r\n if (this.IdsAlertasPanicoActivas.size > 0) {\r\n this.startFlashingTitle();\r\n }\r\n // Si hay nuevas alertas, dispara notificacion sonora\r\n if (newAlerts.length > 0) {\r\n this.playSound();\r\n }\r\n } else {\r\n // Si no hay alertas en la respuesta, limpiar la lista\r\n this.IdsAlertasPanicoActivas.clear();\r\n this.stopFlashingTitle();\r\n }\r\n // Actualizar localStorage con los IDs activos\r\n localStorage.setItem('ALERTAS_PANICO_ACTIVAS_WM', JSON.stringify(Array.from(this.IdsAlertasPanicoActivas)));\r\n });\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n// Material Symbols Outlined (rellena) registrada con un nombre propio para que no choque con la\r\n// versión de Material Symbols o Material Icons que cargue la página que aloja el menú.\r\nconst FAMILIA = 'WM Menu Symbols';\r\nconst URL_CSS = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,1,0';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WmMenuFuenteIconosService {\r\n\r\n private iniciada = false;\r\n\r\n cargar(): void {\r\n if (this.iniciada) {\r\n return;\r\n }\r\n this.iniciada = true;\r\n\r\n const estilo = document.createElement('style');\r\n estilo.textContent = `.wm-menu-iconos {\r\n font-family: '${FAMILIA}';\r\n font-weight: normal;\r\n font-style: normal;\r\n font-size: 24px;\r\n line-height: 1;\r\n letter-spacing: normal;\r\n text-transform: none;\r\n display: inline-block;\r\n white-space: nowrap;\r\n word-wrap: normal;\r\n direction: ltr;\r\n font-feature-settings: 'liga';\r\n -webkit-font-smoothing: antialiased;\r\n }`;\r\n document.head.appendChild(estilo);\r\n\r\n // Oculta los iconos mientras carga la fuente para que no se vea el nombre del icono como texto.\r\n const ocultar = document.createElement('style');\r\n ocultar.textContent = '.wm-menu-iconos { visibility: hidden; }';\r\n document.head.appendChild(ocultar);\r\n\r\n // Se lee la URL del archivo desde el CSS de Google Fonts en lugar de fijarla, porque cambia con cada versión.\r\n fetch(URL_CSS)\r\n .then(resp => resp.text())\r\n .then(css => {\r\n const urlFuente = /url\\(([^)]+)\\)/.exec(css)[1];\r\n const fuente = new (window as any).FontFace(FAMILIA, `url(${urlFuente})`);\r\n (document as any).fonts.add(fuente);\r\n return fuente.load();\r\n })\r\n .catch(error => console.error('wm-menu: no se pudo cargar la fuente de iconos', error))\r\n .then(() => document.head.removeChild(ocultar));\r\n }\r\n}\r\n","import { Component, OnInit, Input } from '@angular/core';\r\nimport { MenuPrincipal } from './model/wm-menu-principal.model';\r\nimport { MenuSecundario } from './model/wm-menu-cuenta.model';\r\nimport { WmMenuServicioService } from './services/wm-menu-servicio.service';\r\nimport { JwtHelperService } from '@auth0/angular-jwt';\r\nimport { WmMenuAlertaPanicoService } from './services/wm-menu-alerta-panico.service';\r\nimport { WmMenuFuenteIconosService } from './services/wm-menu-fuente-iconos.service';\r\n\r\n@Component({\r\n selector: 'wm-menu',\r\n templateUrl: './wm-menu.component.html',\r\n styleUrls: ['./wm-menu.component.scss']\r\n})\r\nexport class WmMenuComponent implements OnInit {\r\n @Input() logo: string;\r\n @Input() colorFondo: string;\r\n @Input() colorTexto: string;\r\n @Input() menuPrincipal: MenuPrincipal[];\r\n @Input() menuSecundario: MenuSecundario[];\r\n\r\n @Input() urlMenu: string; \r\n @Input() token: string;\r\n @Input() urlCuentaSeguridad: string;\r\n @Input() activar2fa: string;\r\n @Input() urlguiasOnline: string;\r\n @Input() urlObtenerAlertasPanico: string;\r\n @Input() urlObtenerParametro: string;\r\n @Input() rutaAudio: string;\r\n\r\n @Input() nombreCliente: string;\r\n @Input() nombreUsuario: string;\r\n @Input() versionWeb: string;\r\n @Input() urlBaseAlmacenamiento: string;\r\n\r\n @Input() urlIdiomas: string;\r\n\r\n // Asistente de IA \"Pregúntale a tus datos\" como opción del menú (reemplaza el botón flotante).\r\n // El gateo real lo hace el menú: carga las funciones del usuario (urlObtenerFunciones + token) y\r\n // muestra el asistente solo si tiene WebChatConsultaIA. `mostrarAsistente` es un override opcional\r\n // (ej. harness/dev) que como web component llega string, por eso el getter puedeAsistente.\r\n @Input() urlObtenerFunciones: string;\r\n @Input() mostrarAsistente: boolean | string = false;\r\n @Input() urlAsistenteConsultar: string;\r\n @Input() idiomaAsistente: string = 'es-CO';\r\n asistenteAbierto = false;\r\n private funcionesUsuario: any[] = [];\r\n\r\n get puedeAsistente(): boolean {\r\n const forzado = this.mostrarAsistente === true || this.mostrarAsistente === 'true' || this.mostrarAsistente === '1';\r\n const tienePermiso = this.funcionesUsuario.some((f: any) => f.CodigoLogica === 'WebChatConsultaIA');\r\n return forzado || tienePermiso;\r\n }\r\n\r\n menuPrincipalSel: MenuPrincipal;\r\n menuSecundarioSel: MenuSecundario = new MenuSecundario();\r\n menuLateralAbierto: Boolean = false;\r\n porcentajeUtilizado : number;\r\n menuIdioma : any = [];\r\n private intervaloPeticionesMs = 60000;\r\n\r\n constructor(private wmMenuServicioService: WmMenuServicioService, private alertaPanicoService: WmMenuAlertaPanicoService,\r\n private fuenteIconosService: WmMenuFuenteIconosService) { }\r\n\r\n ngOnInit(): void {\r\n this.fuenteIconosService.cargar();\r\n this.cargarMenuCuenta();\r\n\r\n this.alertaPanicoService.iniciarProceso(this.intervaloPeticionesMs, () => this.alertaPanicoService.revisarAlertasPendientes(this.urlObtenerAlertasPanico, this.token), this.urlObtenerParametro, this.token, this.rutaAudio);\r\n\r\n // Carga las funciones del usuario para gatear el asistente (puedeAsistente / WebChatConsultaIA).\r\n // Si falla (ej. 401), queda vacía y el asistente no se muestra.\r\n if (this.urlObtenerFunciones && this.token) {\r\n this.wmMenuServicioService\r\n .funcionesObtener(this.urlObtenerFunciones, this.token)\r\n .subscribe(\r\n (resp) => { this.funcionesUsuario = resp ?? []; },\r\n () => { this.funcionesUsuario = []; }\r\n );\r\n }\r\n\r\n if (this.urlMenu && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.wmMenuServicioService\r\n .menuApiObtener(this.urlMenu, decodedToken[\"id_usuario\"], this.token)\r\n .subscribe((resp) => {\r\n this.menuPrincipal = this.wmMenuServicioService.mapearMenu(resp);\r\n });\r\n }\r\n\r\n if (this.urlIdiomas && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.wmMenuServicioService\r\n .menuIdiomasObtener(this.urlIdiomas, decodedToken[\"id_usuario\"], this.token)\r\n .subscribe((resp) => {\r\n this.menuIdioma = resp;\r\n this.cargarMenuCuenta();\r\n });\r\n }\r\n\r\n if (this.urlBaseAlmacenamiento && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.wmMenuServicioService\r\n .almacenamientoApiObtener(this.urlBaseAlmacenamiento, decodedToken[\"id_usuario\"], this.token)\r\n .subscribe((resp) => {\r\n let utilizado = resp[0] && resp[0].Utilizado ? resp[0].Utilizado : 0;\r\n let total = resp[0] && resp[0].Total ? resp[0].Total : 0;\r\n this.porcentajeUtilizado = Math.round((utilizado / total) * 100);\r\n });\r\n }\r\n }\r\n\r\n clickMenuPrincipal(i: number) {\r\n if (this.menuPrincipal[i].hijos && this.menuPrincipal[i].hijos.length) {\r\n if (this.menuPrincipalSel == this.menuPrincipal[i]) {\r\n this.menuPrincipalSel = null;\r\n } else {\r\n this.menuPrincipalSel = this.menuPrincipal[i];\r\n }\r\n }\r\n }\r\n\r\n clickMenuSecundario(i: number) {\r\n this.menuSecundarioSel = this.menuSecundario[i];\r\n this.menuPrincipalSel = null;\r\n }\r\n\r\n cargarMenuCuenta(){\r\n if (this.urlCuentaSeguridad && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.menuSecundario = [{\r\n titulo: decodedToken[\"unique_name\"],\r\n icono: \"account_circle\",\r\n hijos: [\r\n { titulo: decodedToken[\"unique_name\"], url: \"\", icono: \"person\" },\r\n { titulo: this.menuIdioma && this.menuIdioma.CambiarContrasenna ? this.menuIdioma.CambiarContrasenna : \"Cambiar contraseña\", url: this.urlCuentaSeguridad + \"CambioContrasena\", icono: \"vpn_key\" },\r\n this.activar2fa == \"1\" ? { titulo: this.menuIdioma && this.menuIdioma.Configurar2fa ? this.menuIdioma.Configurar2fa : \"Configurar 2FA\", url: this.urlCuentaSeguridad + \"Habilitacion2FA\", icono: \"verified_user\" } : null,\r\n this.urlguiasOnline != null && this.urlguiasOnline !== \"\" && this.urlguiasOnline?.length != 0 ? { titulo: this.menuIdioma && this.menuIdioma.guiasOnline ? this.menuIdioma.guiasOnline : \"Guias Online\", url: this.urlguiasOnline, icono: \"menu_book\" } : null,\r\n { titulo: this.menuIdioma && this.menuIdioma.CerrarSesion ? this.menuIdioma.CerrarSesion : \"Cerrar sesión\", url: this.urlCuentaSeguridad + \"CerrarSesion\", icono: \"exit_to_app\" }].filter(hijo => hijo != null),\r\n }];\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n// Envoltorio de la Web Speech API (SpeechRecognition) del navegador — dictado de voz a texto,\r\n// 100% cliente, sin backend. Soportado en Chrome/Edge; SIN soporte en Firefox y de forma\r\n// inconsistente en Safari (limitación real del navegador, no de esta implementación).\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ReconocimientoVozService {\r\n private reconocimiento: any = null;\r\n\r\n estaSoportado(): boolean {\r\n return !!(this.obtenerConstructor());\r\n }\r\n\r\n // onResultado se llama con el texto reconocido hasta el momento (incluye resultados\r\n // provisionales — interimResults: true — para que el cuadro de texto se vea llenar en vivo).\r\n // onFin se llama cuando el reconocimiento termina, ya sea porque el navegador detectó una\r\n // pausa (continuous: false) o porque se llamó a detener().\r\n iniciar(idioma: string, onResultado: (texto: string) => void, onFin: () => void): void {\r\n const SpeechRecognitionCtor = this.obtenerConstructor();\r\n if (!SpeechRecognitionCtor) {\r\n onFin();\r\n return;\r\n }\r\n\r\n this.detener();\r\n\r\n this.reconocimiento = new SpeechRecognitionCtor();\r\n this.reconocimiento.lang = idioma;\r\n this.reconocimiento.continuous = false;\r\n this.reconocimiento.interimResults = true;\r\n\r\n this.reconocimiento.onresult = (evento: any) => {\r\n const texto = Array.from(evento.results)\r\n .map((resultado: any) => resultado[0].transcript)\r\n .join(' ');\r\n onResultado(texto);\r\n };\r\n\r\n this.reconocimiento.onerror = (evento: any) => {\r\n // Motivos típicos (event.error de SpeechRecognitionErrorEvent): \"not-allowed\" (permiso de\r\n // micrófono denegado o sitio sin HTTPS/localhost), \"no-speech\", \"audio-capture\" (sin\r\n // micrófono), \"network\". Se deja en consola porque no hay backend que lo registre y el\r\n // navegador no explica el motivo en la UI.\r\n console.error('Reconocimiento de voz: error -', evento?.error);\r\n this.reconocimiento = null;\r\n onFin();\r\n };\r\n\r\n this.reconocimiento.onend = () => {\r\n this.reconocimiento = null;\r\n onFin();\r\n };\r\n\r\n try {\r\n this.reconocimiento.start();\r\n } catch (e) {\r\n console.error('Reconocimiento de voz: no se pudo iniciar -', e);\r\n this.reconocimiento = null;\r\n onFin();\r\n }\r\n }\r\n\r\n detener(): void {\r\n if (this.reconocimiento) {\r\n this.reconocimiento.onend = null;\r\n this.reconocimiento.onerror = null;\r\n this.reconocimiento.stop();\r\n this.reconocimiento = null;\r\n }\r\n }\r\n\r\n private obtenerConstructor(): any {\r\n return (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition || null;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\r\nimport { Observable, throwError } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport { JwtHelperService } from '@auth0/angular-jwt';\r\n\r\nexport interface EConsultaDinamicaApi {\r\n Entidad: string;\r\n Where?: string;\r\n Select?: string;\r\n GroupBy?: string;\r\n OrderBy?: string;\r\n Take: number;\r\n Skip: number;\r\n}\r\n\r\nexport interface RespuestaAsistenteDatos {\r\n Resultado: any[];\r\n Consulta: EConsultaDinamicaApi;\r\n Proveedor: string;\r\n Descripcion?: string;\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class AsistenteDatosApiService {\r\n // La fija el componente desde su @Input urlConsultar (reemplaza WmChatConfigService.urlConsultar).\r\n public url = '';\r\n\r\n // Mismo origen del JWT que WmSeguridadService.getJWT() en wm-chat: localStorage['WMTKN'],\r\n // descartado si está vencido. Se replica aquí para que el header Authorization sea idéntico\r\n // al del chat original sin depender de un servicio de config externo.\r\n private readonly TOKEN_KEY = 'WMTKN';\r\n private readonly jwtHelper = new JwtHelperService();\r\n\r\n constructor(private http: HttpClient) {}\r\n\r\n consultar(pregunta: string, proveedor?: string): Observable<RespuestaAsistenteDatos> {\r\n const headers = new HttpHeaders({\r\n Authorization: `Bearer ${this.obtenerJWT()}`,\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n });\r\n\r\n return this.http\r\n .post<RespuestaAsistenteDatos>(\r\n this.url,\r\n { Pregunta: pregunta, Proveedor: proveedor },\r\n { headers }\r\n )\r\n .pipe(\r\n catchError((error) => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n\r\n private obtenerJWT(): string {\r\n const jwt = localStorage.getItem(this.TOKEN_KEY);\r\n\r\n if (jwt) {\r\n try {\r\n return this.jwtHelper.isTokenExpired(jwt) ? null : jwt;\r\n } catch {}\r\n }\r\n return null;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport * as XLSX from 'xlsx';\r\n\r\n// Exporta/copia el resultado tabular del asistente (\"Pregúntale a tus Datos\"). El resultado ya\r\n// llega como arreglo de objetos (una clave por columna, ver RespuestaAsistenteDatos.Resultado), así\r\n// que no hay que parsear HTML: se recorre directo.\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class TablaExportService {\r\n // Separador del CSV: punto y coma. Excel en configuración regional ES (la de los usuarios WM)\r\n // usa ';' como separador de lista, así que al abrir el .csv las columnas quedan separadas sin\r\n // tener que importar con asistente. El TSV del portapapeles usa TAB, que Excel pega en columnas\r\n // sin depender de la config regional.\r\n private readonly SEPARADOR_CSV = ';';\r\n\r\n columnas(filas: any[]): string[] {\r\n return filas && filas.length ? Object.keys(filas[0]) : [];\r\n }\r\n\r\n private valorCelda(valor: any): string {\r\n if (valor === null || valor === undefined) {\r\n return '';\r\n }\r\n return String(valor);\r\n }\r\n\r\n // TSV para el portapapeles: se pega directo en Excel/Sheets en columnas. Los TAB y saltos de\r\n // línea dentro de una celda se neutralizan a espacio para no romper la cuadrícula al pegar.\r\n private aTsv(filas: any[]): string {\r\n const cols = this.columnas(filas);\r\n const limpiar = (v: string) => v.replace(/\\t/g, ' ').replace(/\\r?\\n/g, ' ');\r\n const encabezado = cols.map(limpiar).join('\\t');\r\n const cuerpo = filas.map((fila) => cols.map((c) => limpiar(this.valorCelda(fila[c]))).join('\\t'));\r\n return [encabezado, ...cuerpo].join('\\n');\r\n }\r\n\r\n async copiar(filas: any[]): Promise<void> {\r\n const tsv = this.aTsv(filas);\r\n\r\n if (navigator.clipboard && navigator.clipboard.writeText) {\r\n await navigator.clipboard.writeText(tsv);\r\n return;\r\n }\r\n\r\n // Fallback para contextos sin Clipboard API (http no seguro, navegadores viejos).\r\n const area = document.createElement('textarea');\r\n area.value = tsv;\r\n area.style.position = 'fixed';\r\n area.style.left = '-9999px';\r\n document.body.appendChild(area);\r\n area.select();\r\n try {\r\n document.execCommand('copy');\r\n } finally {\r\n document.body.removeChild(area);\r\n }\r\n }\r\n\r\n private escaparCsv(valor: string): string {\r\n if (valor.indexOf('\"') >= 0 || valor.indexOf(this.SEPARADOR_CSV) >= 0 || /[\\r\\n]/.test(valor)) {\r\n return '\"' + valor.replace(/\"/g, '\"\"') + '\"';\r\n }\r\n return valor;\r\n }\r\n\r\n descargarCsv(filas: any[], nombreBase: string): void {\r\n const cols = this.columnas(filas);\r\n const lineas = [\r\n cols.map((c) => this.escaparCsv(c)).join(this.SEPARADOR_CSV),\r\n ...filas.map((fila) => cols.map((c) => this.escaparCsv(this.valorCelda(fila[c]))).join(this.SEPARADOR_CSV)),\r\n ];\r\n // BOM UTF-8 () para que Excel muestre tildes y ñ correctamente.\r\n const contenido = '' + lineas.join('\\r\\n');\r\n const blob = new Blob([contenido], { type: 'text/csv;charset=utf-8;' });\r\n this.descargarBlob(blob, nombreBase + '.csv');\r\n }\r\n\r\n descargarXlsx(filas: any[], nombreBase: string): void {\r\n const hoja = XLSX.utils.json_to_sheet(filas);\r\n const libro = XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(libro, hoja, 'Datos');\r\n // XLSX.writeFile arma el Blob y dispara la descarga en el navegador.\r\n XLSX.writeFile(libro, nombreBase + '.xlsx');\r\n }\r\n\r\n private descargarBlob(blob: Blob, nombreArchivo: string): void {\r\n const url = URL.createObjectURL(blob);\r\n const enlace = document.createElement('a');\r\n enlace.href = url;\r\n enlace.download = nombreArchivo;\r\n document.body.appendChild(enlace);\r\n enlace.click();\r\n document.body.removeChild(enlace);\r\n setTimeout(() => URL.revokeObjectURL(url));\r\n }\r\n}\r\n","import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';\r\nimport { ReconocimientoVozService } from './reconocimiento-voz.service';\r\nimport { AsistenteDatosApiService } from './asistente-datos-api.service';\r\nimport { TablaExportService } from './tabla-export.service';\r\n\r\nexport interface MensajeAsistenteDatos {\r\n deUsuario: boolean;\r\n texto?: string;\r\n descripcion?: string;\r\n resultado?: any[];\r\n proveedor?: string;\r\n esError?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'wm-asistente-datos',\r\n templateUrl: './asistente-datos.component.html',\r\n styleUrls: ['./asistente-datos.component.scss'],\r\n})\r\nexport class AsistenteDatosComponent {\r\n @ViewChild('mensajesContainer') private mensajesContainer?: ElementRef<HTMLDivElement>;\r\n\r\n // La apertura/cierre del panel la controla el padre (el menú). El panel solo se renderiza\r\n // cuando `abierto` es true y avisa, vía `cerrarChange`, cuando el usuario toca la X.\r\n @Input() abierto = false;\r\n\r\n // URL del POST de consulta. Se refleja en el api service (propiedad `url`), que es donde se usa.\r\n @Input() set urlConsultar(valor: string) {\r\n if (valor) {\r\n this.asistenteDatosApiService.url = valor;\r\n }\r\n }\r\n\r\n // Idioma para el reconocimiento de voz (Web Speech API).\r\n @Input() idioma = 'es-CO';\r\n\r\n @Output() cerrarChange = new EventEmitter<void>();\r\n\r\n public mensajes: MensajeAsistenteDatos[] = [];\r\n public borrador = '';\r\n // Alterna el alto de la caja del mensaje (compacta ↔ expandida), igual que el \"pedir cambios\"\r\n // del asistente de IA del generador de formularios (ver filasBorrador / onClickExpandirBorrador).\r\n public borradorExpandido = false;\r\n public consultando = false;\r\n // \"Gemini\" o \"Groq\" — mismo selector que el asistente de generación de formularios\r\n // (ver ProveedorIAServicio en el backend).\r\n public proveedorSeleccionado: 'Gemini' | 'Groq' = 'Gemini';\r\n // Dictado por voz (Web Speech API) — sin soporte en Firefox, inconsistente en Safari.\r\n public escuchando = false;\r\n\r\n // Tabla abierta en el modal \"ampliar\" (null = modal cerrado). El panel del chat es angosto y\r\n // recorta las columnas; el modal muestra la misma tabla a todo el ancho de la pantalla.\r\n public tablaAmpliada: any[] | null = null;\r\n public descripcionAmpliada = '';\r\n // Aviso efímero \"Tabla copiada\" tras copiar al portapapeles.\r\n public copiadoAviso = false;\r\n\r\n // Preguntas ya verificadas como respondibles hoy (whitelist + contrato de la IA — ver\r\n // ChatConsultaWhitelistServicio/ChatConsultaPromptServicio en el backend), mostradas como chips\r\n // de sugerencia en el estado vacío del chat.\r\n public chipsSugeridos: string[] = [\r\n '¿Cuántos formularios se diligenciaron hoy?',\r\n '¿Cuántos formularios se diligenciaron esta semana?',\r\n 'Muéstrame los últimos 10 formularios diligenciados',\r\n ];\r\n\r\n constructor(\r\n private asistenteDatosApiService: AsistenteDatosApiService,\r\n private reconocimientoVoz: ReconocimientoVozService,\r\n private tablaExport: TablaExportService\r\n ) {}\r\n\r\n // El padre abre/cierra el panel; aquí solo se avisa que el usuario pidió cerrarlo (botón X).\r\n cerrar(): void {\r\n this.cerrarChange.emit();\r\n }\r\n\r\n // Caja del mensaje compacta (1 fila, como era el chat originalmente) ↔ expandida (6 filas).\r\n // El botón de expandir es el mismo patrón del \"pedir cambios\" del generador.\r\n get filasBorrador(): number {\r\n return this.borradorExpandido ? 6 : 1;\r\n }\r\n\r\n onClickExpandirBorrador(): void {\r\n this.borradorExpandido = !this.borradorExpandido;\r\n }\r\n\r\n get micDisponible(): boolean {\r\n return this.reconocimientoVoz.estaSoportado();\r\n }\r\n\r\n onClickMicrofono(): void {\r\n if (this.escuchando) {\r\n this.reconocimientoVoz.detener();\r\n this.escuchando = false;\r\n return;\r\n }\r\n\r\n if (!this.reconocimientoVoz.estaSoportado()) {\r\n return;\r\n }\r\n\r\n // El resultado del reconocimiento no incluye lo que ya estaba escrito — se guarda antes de\r\n // empezar y se antepone en cada actualización (que llega con la transcripción COMPLETA de\r\n // esta sesión de escucha, no un incremento) para no perder lo que ya había en el campo.\r\n const textoPrevio = this.borrador.trim();\r\n this.escuchando = true;\r\n this.reconocimientoVoz.iniciar(\r\n this.idioma,\r\n (texto) => (this.borrador = textoPrevio ? `${textoPrevio} ${texto}` : texto),\r\n () => (this.escuchando = false)\r\n );\r\n }\r\n\r\n onClickEnviar(textoPreset?: string): void {\r\n const pregunta = (textoPreset ?? this.borrador).trim();\r\n if (!pregunta || this.consultando) {\r\n return;\r\n }\r\n\r\n this.mensajes.push({ deUsuario: true, texto: pregunta });\r\n this.borrador = '';\r\n\r\n // Sin url de consulta no se hace la petición: el usuario ve el mismo error genérico que\r\n // cuando la API falla.\r\n if (!this.asistenteDatosApiService.url) {\r\n this.mensajes.push({\r\n deUsuario: false,\r\n texto: 'No se pudo procesar la consulta.',\r\n esError: true,\r\n });\r\n this.scrollAlFinal();\r\n return;\r\n }\r\n\r\n this.consultando = true;\r\n this.scrollAlFinal();\r\n\r\n this.asistenteDatosApiService.consultar(pregunta, this.proveedorSeleccionado).subscribe({\r\n // El tipo (RespuestaAsistenteDatos) se infiere del Observable: importar la interfaz\r\n // dejaba un import a un símbolo inexistente en el JS de la librería (aviso de rollup).\r\n next: (respuesta) => {\r\n this.consultando = false;\r\n this.mensajes.push({\r\n deUsuario: false,\r\n descripcion: respuesta.Descripcion,\r\n resultado: respuesta.Resultado ?? [],\r\n proveedor: respuesta.Proveedor,\r\n });\r\n this.scrollAlFinal();\r\n },\r\n error: (error) => {\r\n this.consultando = false;\r\n this.mensajes.push({\r\n deUsuario: false,\r\n texto: error?.Mensaje || 'No se pudo procesar la consulta.',\r\n esError: true,\r\n });\r\n this.scrollAlFinal();\r\n },\r\n });\r\n }\r\n\r\n // El nuevo mensaje recién se refleja en el DOM después del siguiente ciclo de detección de\r\n // cambios — por eso el scrollTop se ajusta en un setTimeout(0), no inmediatamente después del\r\n // push, para que scrollHeight ya incluya el mensaje agregado.\r\n private scrollAlFinal(): void {\r\n setTimeout(() => {\r\n const elemento = this.mensajesContainer?.nativeElement;\r\n if (elemento) {\r\n elemento.scrollTop = elemento.scrollHeight;\r\n }\r\n });\r\n }\r\n\r\n columnasDe(resultado: any[]): string[] {\r\n return resultado.length ? Object.keys(resultado[0]) : [];\r\n }\r\n\r\n // El backend devuelve un conteo (ChatConsultaIAServicio.EjecutarConteo) como una sola fila con\r\n // una sola columna llamada literalmente \"Resultado\" — se muestra como número grande en vez de\r\n // como tabla de una celda.\r\n esConteo(resultado: any[]): boolean {\r\n return resultado?.length === 1 && Object.keys(resultado[0]).length === 1 && 'Resultado' in resultado[0];\r\n }\r\n\r\n // Listado con una sola columna (ej. una lista de nombres/ids) — se muestra como texto simple\r\n // en vez de una tabla de una sola columna repetida.\r\n esListaSimple(resultado: any[]): boolean {\r\n return resultado?.length > 0 && !this.esConteo(resultado) && this.columnasDe(resultado).length === 1;\r\n }\r\n\r\n textoListaSimple(resultado: any[]): string {\r\n const columna = this.columnasDe(resultado)[0];\r\n return resultado.map((fila) => fila[columna]).join(', ');\r\n }\r\n\r\n // --- Acciones sobre la tabla de resultados (ampliar / copiar / exportar) ---\r\n\r\n ampliar(resultado: any[], descripcion?: string): void {\r\n this.tablaAmpliada = resultado;\r\n this.descripcionAmpliada = descripcion || '';\r\n }\r\n\r\n cerrarAmpliada(): void {\r\n this.tablaAmpliada = null;\r\n this.descripcionAmpliada = '';\r\n }\r\n\r\n async copiar(resultado: any[]): Promise<void> {\r\n try {\r\n await this.tablaExport.copiar(resultado);\r\n this.copiadoAviso = true;\r\n setTimeout(() => (this.copiadoAviso = false), 1800);\r\n } catch {\r\n // Copiar puede fallar por permisos del portapapeles; se ignora en silencio (el usuario\r\n // aún puede ampliar y exportar).\r\n }\r\n }\r\n\r\n exportarCsv(resultado: any[]): void {\r\n this.tablaExport.descargarCsv(resultado, this.nombreArchivo());\r\n }\r\n\r\n exportarXlsx(resultado: any[]): void {\r\n this.tablaExport.descargarXlsx(resultado, this.nombreArchivo());\r\n }\r\n\r\n private nombreArchivo(): string {\r\n const ahora = new Date();\r\n const dos = (n: number) => String(n).padStart(2, '0');\r\n return (\r\n 'asistente-datos-' +\r\n ahora.getFullYear() +\r\n dos(ahora.getMonth() + 1) +\r\n dos(ahora.getDate()) +\r\n '-' +\r\n dos(ahora.getHours()) +\r\n dos(ahora.getMinutes())\r\n );\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\n\r\nimport { MatToolbarModule } from '@angular/material/toolbar';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatSidenavModule} from '@angular/material/sidenav';\r\nimport { MatListModule } from '@angular/material/list';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatMenuModule } from '@angular/material/menu';\r\nimport { MatTableModule } from '@angular/material/table';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatRippleModule } from \"@angular/material/core\";\r\nimport { FormsModule } from '@angular/forms';\r\n\r\nimport { WmMenuComponent } from './wm-menu/wm-menu.component';\r\nimport { AsistenteDatosComponent } from './wm-menu/asistente-datos/asistente-datos.component';\r\nimport { HttpClientModule } from '@angular/common/http';\r\nimport { BrowserModule } from '@angular/platform-browser';\r\nimport { JwtModule } from '@auth0/angular-jwt';\r\n\r\n\r\n@NgModule({\r\n declarations: [WmMenuComponent, AsistenteDatosComponent],\r\n imports: [\r\n BrowserModule,\r\n FormsModule,\r\n MatToolbarModule,\r\n MatSidenavModule,\r\n MatListModule,\r\n MatButtonModule,\r\n MatIconModule,\r\n MatMenuModule,\r\n MatTableModule,\r\n MatTooltipModule,\r\n MatRippleModule,\r\n HttpClientModule,\r\n JwtModule\r\n ],\r\n exports: [WmMenuComponent]\r\n})\r\nexport class WmMenuModule { }\r\n","/*\r\n * Public API Surface of wm-menu\r\n */\r\n\r\nexport * from './lib/wm-menu/wm-menu.component';\r\nexport * from './lib/wm-menu/services/wm-menu-servicio.service';\r\nexport * from './lib/wm-menu/services/wm-menu-alerta-panico.service';\r\nexport * from './lib/wm-menu.module';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n\nexport {AsistenteDatosApiService as ɵc} from './lib/wm-menu/asistente-datos/asistente-datos-api.service';\nexport {AsistenteDatosComponent as ɵb} from './lib/wm-menu/asistente-datos/asistente-datos.component';\nexport {ReconocimientoVozService as ɵd} from './lib/wm-menu/asistente-datos/reconocimiento-voz.service';\nexport {TablaExportService as ɵe} from './lib/wm-menu/asistente-datos/tabla-export.service';\nexport {WmMenuFuenteIconosService as ɵa} from './lib/wm-menu/services/wm-menu-fuente-iconos.service';"],"names":["XLSX.utils","XLSX.writeFile"],"mappings":"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"}
1
+ {"version":3,"file":"wm-menu.js","sources":["ng://wm-menu/lib/wm-menu/model/wm-menu-cuenta.model.ts","ng://wm-menu/lib/wm-menu/services/wm-menu-servicio.service.ts","ng://wm-menu/lib/wm-menu/services/wm-menu-alerta-panico.service.ts","ng://wm-menu/lib/wm-menu/services/wm-menu-fuente-iconos.service.ts","ng://wm-menu/lib/wm-menu/wm-menu.component.ts","ng://wm-menu/lib/wm-menu/asistente-datos/reconocimiento-voz.service.ts","ng://wm-menu/lib/wm-menu/asistente-datos/asistente-datos-api.service.ts","ng://wm-menu/lib/wm-menu/asistente-datos/tabla-export.service.ts","ng://wm-menu/lib/wm-menu/asistente-datos/asistente-datos.component.ts","ng://wm-menu/lib/wm-menu.module.ts","ng://wm-menu/public-api.ts","ng://wm-menu/wm-menu.ts"],"sourcesContent":["export class MenuSecundario {\r\n icono: string;\r\n titulo: string;\r\n hijos: MenuSecundarioHijo[] = [];\r\n}\r\n\r\nexport class MenuSecundarioHijo {\r\n icono: string;\r\n titulo: string;\r\n url: string;\r\n}","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';\r\nimport { map, catchError } from 'rxjs/operators';\r\nimport { throwError, Observable } from 'rxjs';\r\nimport { DomSanitizer } from '@angular/platform-browser';\r\nimport { MatIconRegistry } from '@angular/material/icon';\r\nimport { MenuPrincipal } from '../model/wm-menu-principal.model';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WmMenuServicioService {\r\n\r\n constructor(private http: HttpClient, private iconRegistry: MatIconRegistry, private sanitizer: DomSanitizer) { }\r\n\r\n menuApiObtener(url:string, idUsuario: string, token:string, codLogicaParametro = \"\"): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n \r\n let myParams = new HttpParams();\r\n if (codLogicaParametro.length > 0) {\r\n myParams = myParams.append(\"codLogica\", codLogicaParametro);\r\n }\r\n myParams = myParams.append(\"ctrlActivo\", \"true\");\r\n myParams = myParams.append(\"conPadres\", \"true\");\r\n if (idUsuario != null)\r\n myParams = myParams.append(\"idUsuario\", idUsuario.toString());\r\n\r\n return this.http.get(url, { headers, params: myParams }).pipe(\r\n map(resp => {\r\n return resp;\r\n }),\r\n catchError(error => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n\r\n mapearMenu(respApi: any): MenuPrincipal[] {\r\n respApi = respApi.sort((a, b) => a.Posicion > b.Posicion?\"1\":\"-1\");\r\n\r\n for (const key in respApi) {\r\n const element = respApi[key];\r\n if (element.Icono.startsWith(\"http\")) {\r\n var iconSvg = 'wm-icon-menu-' + key;\r\n this.iconRegistry.addSvgIcon(\r\n iconSvg,\r\n this.sanitizer.bypassSecurityTrustResourceUrl(element.Icono));\r\n respApi[key].Icono = iconSvg;\r\n }\r\n }\r\n\r\n return this.obtenerMenu(respApi);\r\n }\r\n\r\n\r\n private obtenerMenu(respApi: any, idMenuPadre?: Number): MenuPrincipal[] {\r\n var menu: MenuPrincipal[] = [];\r\n for (const key in respApi) {\r\n if (respApi[key].IdMenuPadre == idMenuPadre || (!idMenuPadre && respApi[key].IdMenuPadre == null)) {\r\n menu.push({\r\n titulo: respApi[key].IdiomaRecurso,\r\n url: respApi[key].Url,\r\n icono: respApi[key].Icono,\r\n descripcion: respApi[key].Descripcion,\r\n hijos: this.obtenerMenu(respApi, respApi[key].IdMenu)\r\n });\r\n }\r\n }\r\n return menu;\r\n }\r\n\r\n menuIdiomasObtener(url:string, idUsuario: string, token:string): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n\r\n return this.http.get(url).pipe(\r\n map(resp => {\r\n return resp;\r\n }),\r\n catchError(error => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n \r\n almacenamientoApiObtener(url:string, idUsuario: string, token:string): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n \r\n let myParams = new HttpParams();\r\n\r\n if (idUsuario != null)\r\n myParams = myParams.append(\"idUsuario\", idUsuario.toString());\r\n \r\n return this.http.get(url, { headers, params: myParams }).pipe(\r\n map(resp => {\r\n return resp;\r\n }),\r\n catchError(error => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n\r\n // Funciones (permisos) del usuario autenticado, para gatear features del menú como el\r\n // asistente \"Pregúntale a tus datos\" (CodigoLogica === 'WebChatConsultaIA').\r\n funcionesObtener(url: string, token: string): Observable<any> {\r\n const headers = new HttpHeaders({\r\n 'Authorization': `Bearer ${token}`\r\n });\r\n\r\n return this.http.get(url, { headers }).pipe(\r\n map(resp => resp),\r\n catchError(error => throwError(error.error))\r\n );\r\n }\r\n}","import { Injectable } from '@angular/core';\r\nimport { JwtHelperService } from '@auth0/angular-jwt';\r\nimport { WmMenuServicioService } from './wm-menu-servicio.service';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WmMenuAlertaPanicoService {\r\n\r\n private intervalId: any;\r\n private alternateTitle = 'Alerta de Pánico Recibida';\r\n private originalTitle: string;\r\n private audio: HTMLAudioElement | null = null;\r\n private isPlaying = false; // Controla si el sonido ya está reproduciéndose\r\n public formulario: any;\r\n private IdsAlertasPanicoActivas: Set<number> = new Set(); // Almacena los IDs de las alertas ya manejadas\r\n private soundTimeout: any = null; // Controla el temporizador del sonido\r\n private rutaAudio: string;\r\n constructor(private wmMenuServicioService: WmMenuServicioService) { }\r\n\r\n private subscription: any;\r\n private isRunning: boolean = false;\r\n\r\n iniciarProceso(\r\n intervalMs: number,\r\n callback: () => void,\r\n urlObtenerParametro: string,\r\n token: string,\r\n rutaAudio: string\r\n ): void {\r\n this.rutaAudio = rutaAudio;\r\n \r\n const iniciarConInteraccion = () => {\r\n this.wmMenuServicioService\r\n .menuApiObtener(urlObtenerParametro, null, token, 'ReporteAlertasPanico')\r\n .subscribe((resp) => {\r\n // validar si el parametro ReporteAlertasPanico esta encendido\r\n if (resp && resp.length > 0 && resp[0].Valor == 1) {\r\n if (this.isRunning) {\r\n return;\r\n }\r\n // Inicializar la variable desde localStorage\r\n const storedIds = localStorage.getItem('ALERTAS_PANICO_ACTIVAS_WM');\r\n this.IdsAlertasPanicoActivas = storedIds ? new Set(JSON.parse(storedIds)) : new Set();\r\n \r\n const ejecutarProceso = () => {\r\n this.isRunning = true;\r\n callback();\r\n setTimeout(() => {\r\n this.isRunning = false;\r\n ejecutarProceso();\r\n }, intervalMs);\r\n };\r\n \r\n ejecutarProceso();\r\n }\r\n });\r\n };\r\n \r\n ['drag', 'click'].forEach(evento => {\r\n document.addEventListener(\r\n evento,\r\n () => {\r\n iniciarConInteraccion();\r\n },\r\n { once: true }\r\n );\r\n });\r\n\r\n }\r\n \r\n\r\n stopProcess(): void {\r\n this.isRunning = false;\r\n if (this.subscription) {\r\n this.subscription.unsubscribe();\r\n }\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.stopSound();\r\n this.stopFlashingTitle();\r\n }\r\n\r\n playSound(): void {\r\n if (this.isPlaying) return; // Evita reproducir si ya está sonando\r\n\r\n this.isPlaying = true;\r\n if (!this.audio) {\r\n this.audio = new Audio(this.rutaAudio); // Ruta al archivo de sonido\r\n }\r\n\r\n this.audio.loop = true; // Reproducir en bucle\r\n this.audio.play()\r\n .then(() => {\r\n // Detener el sonido después de 10 segundos\r\n this.soundTimeout = setTimeout(() => {\r\n this.stopSound();\r\n }, 10000); // Detener después de 10 segundos\r\n })\r\n .catch(error => {\r\n console.log('Error al reproducir el sonido:', error);\r\n });\r\n }\r\n\r\n stopSound(): void {\r\n if (this.audio) {\r\n this.audio.pause();\r\n this.audio.currentTime = 0; // Reinicia el sonido\r\n }\r\n this.isPlaying = false; // Restablece la bandera\r\n if (this.soundTimeout) {\r\n clearTimeout(this.soundTimeout); // Asegura que el temporizador se borre\r\n this.soundTimeout = null;\r\n }\r\n }\r\n\r\n startFlashingTitle(): void {\r\n let toggle = false;\r\n \r\n // Almacenar el título original si aún no se ha guardado\r\n if (!this.originalTitle) {\r\n this.originalTitle = document.title;\r\n }\r\n \r\n if (!this.intervalId) {\r\n this.intervalId = setInterval(() => {\r\n // Alternar entre el título alternativo y el título original\r\n document.title = toggle ? this.alternateTitle : this.originalTitle;\r\n toggle = !toggle;\r\n }, 1000); // Cambia el título cada segundo\r\n }\r\n }\r\n\r\n stopFlashingTitle(): void {\r\n if (this.intervalId) {\r\n clearInterval(this.intervalId);\r\n this.intervalId = null;\r\n document.title = this.originalTitle; // Restaura a vacío\r\n }\r\n }\r\n\r\n revisarAlertasPendientes(urlObtenerAlertasPanico: string, token: string): void {\r\n const helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(token);\r\n this.wmMenuServicioService\r\n .menuApiObtener(urlObtenerAlertasPanico, decodedToken['id_usuario'], token)\r\n .subscribe((resp) => {\r\n if (resp && resp.length > 0) {\r\n \r\n const alertasIds = resp.map(alerta => alerta.IdAlertaPanico);\r\n\r\n // Eliminar IDs que no están en la respuesta del servicio\r\n this.IdsAlertasPanicoActivas.forEach((id) => {\r\n if (!alertasIds.includes(id)) {\r\n this.IdsAlertasPanicoActivas.delete(id);\r\n }\r\n });\r\n\r\n // Filtrar alertas nuevas\r\n const newAlerts = resp.filter(alerta => !this.IdsAlertasPanicoActivas.has(alerta.IdAlertaPanico));\r\n\r\n // Agregar las nuevas alertas a la lista activa\r\n newAlerts.forEach(alerta => this.IdsAlertasPanicoActivas.add(alerta.IdAlertaPanico));\r\n if (this.IdsAlertasPanicoActivas.size > 0) {\r\n this.startFlashingTitle();\r\n }\r\n // Si hay nuevas alertas, dispara notificacion sonora\r\n if (newAlerts.length > 0) {\r\n this.playSound();\r\n }\r\n } else {\r\n // Si no hay alertas en la respuesta, limpiar la lista\r\n this.IdsAlertasPanicoActivas.clear();\r\n this.stopFlashingTitle();\r\n }\r\n // Actualizar localStorage con los IDs activos\r\n localStorage.setItem('ALERTAS_PANICO_ACTIVAS_WM', JSON.stringify(Array.from(this.IdsAlertasPanicoActivas)));\r\n });\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n// Material Symbols Outlined (rellena) registrada con un nombre propio para que no choque con la\r\n// versión de Material Symbols o Material Icons que cargue la página que aloja el menú.\r\nconst FAMILIA = 'WM Menu Symbols';\r\nconst URL_CSS = 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,1,0';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class WmMenuFuenteIconosService {\r\n\r\n private iniciada = false;\r\n\r\n cargar(): void {\r\n if (this.iniciada) {\r\n return;\r\n }\r\n this.iniciada = true;\r\n\r\n const estilo = document.createElement('style');\r\n estilo.textContent = `.wm-menu-iconos {\r\n font-family: '${FAMILIA}';\r\n font-weight: normal;\r\n font-style: normal;\r\n font-size: 24px;\r\n line-height: 1;\r\n letter-spacing: normal;\r\n text-transform: none;\r\n display: inline-block;\r\n white-space: nowrap;\r\n word-wrap: normal;\r\n direction: ltr;\r\n font-feature-settings: 'liga';\r\n -webkit-font-smoothing: antialiased;\r\n }`;\r\n document.head.appendChild(estilo);\r\n\r\n // Oculta los iconos mientras carga la fuente para que no se vea el nombre del icono como texto.\r\n const ocultar = document.createElement('style');\r\n ocultar.textContent = '.wm-menu-iconos { visibility: hidden; }';\r\n document.head.appendChild(ocultar);\r\n\r\n // Se lee la URL del archivo desde el CSS de Google Fonts en lugar de fijarla, porque cambia con cada versión.\r\n fetch(URL_CSS)\r\n .then(resp => resp.text())\r\n .then(css => {\r\n const urlFuente = /url\\(([^)]+)\\)/.exec(css)[1];\r\n const fuente = new (window as any).FontFace(FAMILIA, `url(${urlFuente})`);\r\n (document as any).fonts.add(fuente);\r\n return fuente.load();\r\n })\r\n .catch(error => console.error('wm-menu: no se pudo cargar la fuente de iconos', error))\r\n .then(() => document.head.removeChild(ocultar));\r\n }\r\n}\r\n","import { Component, OnInit, Input } from '@angular/core';\r\nimport { MenuPrincipal } from './model/wm-menu-principal.model';\r\nimport { MenuSecundario } from './model/wm-menu-cuenta.model';\r\nimport { WmMenuServicioService } from './services/wm-menu-servicio.service';\r\nimport { JwtHelperService } from '@auth0/angular-jwt';\r\nimport { WmMenuAlertaPanicoService } from './services/wm-menu-alerta-panico.service';\r\nimport { WmMenuFuenteIconosService } from './services/wm-menu-fuente-iconos.service';\r\n\r\n@Component({\r\n selector: 'wm-menu',\r\n templateUrl: './wm-menu.component.html',\r\n styleUrls: ['./wm-menu.component.scss']\r\n})\r\nexport class WmMenuComponent implements OnInit {\r\n @Input() logo: string;\r\n @Input() colorFondo: string;\r\n @Input() colorTexto: string;\r\n @Input() menuPrincipal: MenuPrincipal[];\r\n @Input() menuSecundario: MenuSecundario[];\r\n\r\n @Input() urlMenu: string; \r\n @Input() token: string;\r\n @Input() urlCuentaSeguridad: string;\r\n @Input() activar2fa: string;\r\n @Input() urlguiasOnline: string;\r\n @Input() urlObtenerAlertasPanico: string;\r\n @Input() urlObtenerParametro: string;\r\n @Input() rutaAudio: string;\r\n\r\n @Input() nombreCliente: string;\r\n @Input() nombreUsuario: string;\r\n @Input() versionWeb: string;\r\n @Input() urlBaseAlmacenamiento: string;\r\n\r\n @Input() urlIdiomas: string;\r\n\r\n // Asistente de IA \"Pregúntale a tus datos\" como opción del menú (reemplaza el botón flotante).\r\n // El gateo real lo hace el menú: carga las funciones del usuario (urlObtenerFunciones + token) y\r\n // muestra el asistente solo si tiene WebChatConsultaIA. `mostrarAsistente` es un override opcional\r\n // (ej. harness/dev) que como web component llega string, por eso el getter puedeAsistente.\r\n @Input() urlObtenerFunciones: string;\r\n @Input() mostrarAsistente: boolean | string = false;\r\n @Input() urlAsistenteConsultar: string;\r\n @Input() idiomaAsistente: string = 'es-CO';\r\n asistenteAbierto = false;\r\n private funcionesUsuario: any[] = [];\r\n\r\n get puedeAsistente(): boolean {\r\n const forzado = this.mostrarAsistente === true || this.mostrarAsistente === 'true' || this.mostrarAsistente === '1';\r\n const tienePermiso = this.funcionesUsuario.some((f: any) => f.CodigoLogica === 'WebChatConsultaIA');\r\n return forzado || tienePermiso;\r\n }\r\n\r\n menuPrincipalSel: MenuPrincipal;\r\n menuSecundarioSel: MenuSecundario = new MenuSecundario();\r\n menuLateralAbierto: Boolean = false;\r\n porcentajeUtilizado : number;\r\n menuIdioma : any = [];\r\n private intervaloPeticionesMs = 60000;\r\n\r\n constructor(private wmMenuServicioService: WmMenuServicioService, private alertaPanicoService: WmMenuAlertaPanicoService,\r\n private fuenteIconosService: WmMenuFuenteIconosService) { }\r\n\r\n ngOnInit(): void {\r\n this.fuenteIconosService.cargar();\r\n this.cargarMenuCuenta();\r\n\r\n this.alertaPanicoService.iniciarProceso(this.intervaloPeticionesMs, () => this.alertaPanicoService.revisarAlertasPendientes(this.urlObtenerAlertasPanico, this.token), this.urlObtenerParametro, this.token, this.rutaAudio);\r\n\r\n // Carga las funciones del usuario para gatear el asistente (puedeAsistente / WebChatConsultaIA).\r\n // Si falla (ej. 401), queda vacía y el asistente no se muestra.\r\n if (this.urlObtenerFunciones && this.token) {\r\n this.wmMenuServicioService\r\n .funcionesObtener(this.urlObtenerFunciones, this.token)\r\n .subscribe(\r\n (resp) => { this.funcionesUsuario = resp ?? []; },\r\n () => { this.funcionesUsuario = []; }\r\n );\r\n }\r\n\r\n if (this.urlMenu && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.wmMenuServicioService\r\n .menuApiObtener(this.urlMenu, decodedToken[\"id_usuario\"], this.token)\r\n .subscribe((resp) => {\r\n this.menuPrincipal = this.wmMenuServicioService.mapearMenu(resp);\r\n });\r\n }\r\n\r\n if (this.urlIdiomas && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.wmMenuServicioService\r\n .menuIdiomasObtener(this.urlIdiomas, decodedToken[\"id_usuario\"], this.token)\r\n .subscribe((resp) => {\r\n this.menuIdioma = resp;\r\n this.cargarMenuCuenta();\r\n });\r\n }\r\n\r\n if (this.urlBaseAlmacenamiento && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.wmMenuServicioService\r\n .almacenamientoApiObtener(this.urlBaseAlmacenamiento, decodedToken[\"id_usuario\"], this.token)\r\n .subscribe((resp) => {\r\n let utilizado = resp[0] && resp[0].Utilizado ? resp[0].Utilizado : 0;\r\n let total = resp[0] && resp[0].Total ? resp[0].Total : 0;\r\n this.porcentajeUtilizado = Math.round((utilizado / total) * 100);\r\n });\r\n }\r\n }\r\n\r\n clickMenuPrincipal(i: number) {\r\n if (this.menuPrincipal[i].hijos && this.menuPrincipal[i].hijos.length) {\r\n if (this.menuPrincipalSel == this.menuPrincipal[i]) {\r\n this.menuPrincipalSel = null;\r\n } else {\r\n this.menuPrincipalSel = this.menuPrincipal[i];\r\n }\r\n }\r\n }\r\n\r\n clickMenuSecundario(i: number) {\r\n this.menuSecundarioSel = this.menuSecundario[i];\r\n this.menuPrincipalSel = null;\r\n }\r\n\r\n cargarMenuCuenta(){\r\n if (this.urlCuentaSeguridad && this.token) {\r\n var helper = new JwtHelperService();\r\n const decodedToken = helper.decodeToken(this.token);\r\n this.menuSecundario = [{\r\n titulo: decodedToken[\"unique_name\"],\r\n icono: \"account_circle\",\r\n hijos: [\r\n { titulo: decodedToken[\"unique_name\"], url: \"\", icono: \"person\" },\r\n { titulo: this.menuIdioma && this.menuIdioma.CambiarContrasenna ? this.menuIdioma.CambiarContrasenna : \"Cambiar contraseña\", url: this.urlCuentaSeguridad + \"CambioContrasena\", icono: \"vpn_key\" },\r\n this.activar2fa == \"1\" ? { titulo: this.menuIdioma && this.menuIdioma.Configurar2fa ? this.menuIdioma.Configurar2fa : \"Configurar 2FA\", url: this.urlCuentaSeguridad + \"Habilitacion2FA\", icono: \"verified_user\" } : null,\r\n this.urlguiasOnline != null && this.urlguiasOnline !== \"\" && this.urlguiasOnline?.length != 0 ? { titulo: this.menuIdioma && this.menuIdioma.guiasOnline ? this.menuIdioma.guiasOnline : \"Guias Online\", url: this.urlguiasOnline, icono: \"menu_book\" } : null,\r\n { titulo: this.menuIdioma && this.menuIdioma.CerrarSesion ? this.menuIdioma.CerrarSesion : \"Cerrar sesión\", url: this.urlCuentaSeguridad + \"CerrarSesion\", icono: \"exit_to_app\" }].filter(hijo => hijo != null),\r\n }];\r\n }\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n// Envoltorio de la Web Speech API (SpeechRecognition) del navegador — dictado de voz a texto,\r\n// 100% cliente, sin backend. Soportado en Chrome/Edge; SIN soporte en Firefox y de forma\r\n// inconsistente en Safari (limitación real del navegador, no de esta implementación).\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ReconocimientoVozService {\r\n private reconocimiento: any = null;\r\n\r\n estaSoportado(): boolean {\r\n return !!(this.obtenerConstructor());\r\n }\r\n\r\n // onResultado se llama con el texto reconocido hasta el momento (incluye resultados\r\n // provisionales — interimResults: true — para que el cuadro de texto se vea llenar en vivo).\r\n // onFin se llama cuando el reconocimiento termina, ya sea porque el navegador detectó una\r\n // pausa (continuous: false) o porque se llamó a detener().\r\n iniciar(idioma: string, onResultado: (texto: string) => void, onFin: () => void): void {\r\n const SpeechRecognitionCtor = this.obtenerConstructor();\r\n if (!SpeechRecognitionCtor) {\r\n onFin();\r\n return;\r\n }\r\n\r\n this.detener();\r\n\r\n this.reconocimiento = new SpeechRecognitionCtor();\r\n this.reconocimiento.lang = idioma;\r\n this.reconocimiento.continuous = false;\r\n this.reconocimiento.interimResults = true;\r\n\r\n this.reconocimiento.onresult = (evento: any) => {\r\n const texto = Array.from(evento.results)\r\n .map((resultado: any) => resultado[0].transcript)\r\n .join(' ');\r\n onResultado(texto);\r\n };\r\n\r\n this.reconocimiento.onerror = (evento: any) => {\r\n // Motivos típicos (event.error de SpeechRecognitionErrorEvent): \"not-allowed\" (permiso de\r\n // micrófono denegado o sitio sin HTTPS/localhost), \"no-speech\", \"audio-capture\" (sin\r\n // micrófono), \"network\". Se deja en consola porque no hay backend que lo registre y el\r\n // navegador no explica el motivo en la UI.\r\n console.error('Reconocimiento de voz: error -', evento?.error);\r\n this.reconocimiento = null;\r\n onFin();\r\n };\r\n\r\n this.reconocimiento.onend = () => {\r\n this.reconocimiento = null;\r\n onFin();\r\n };\r\n\r\n try {\r\n this.reconocimiento.start();\r\n } catch (e) {\r\n console.error('Reconocimiento de voz: no se pudo iniciar -', e);\r\n this.reconocimiento = null;\r\n onFin();\r\n }\r\n }\r\n\r\n detener(): void {\r\n if (this.reconocimiento) {\r\n this.reconocimiento.onend = null;\r\n this.reconocimiento.onerror = null;\r\n this.reconocimiento.stop();\r\n this.reconocimiento = null;\r\n }\r\n }\r\n\r\n private obtenerConstructor(): any {\r\n return (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition || null;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { HttpClient, HttpHeaders } from '@angular/common/http';\r\nimport { Observable, throwError } from 'rxjs';\r\nimport { catchError } from 'rxjs/operators';\r\nimport { JwtHelperService } from '@auth0/angular-jwt';\r\n\r\nexport interface EConsultaDinamicaApi {\r\n Entidad: string;\r\n Where?: string;\r\n Select?: string;\r\n GroupBy?: string;\r\n OrderBy?: string;\r\n Take: number;\r\n Skip: number;\r\n}\r\n\r\nexport interface RespuestaAsistenteDatos {\r\n Resultado: any[];\r\n Consulta: EConsultaDinamicaApi;\r\n Proveedor: string;\r\n Descripcion?: string;\r\n // 2-3 preguntas de seguimiento acotadas al rol, generadas por el backend según la última consulta.\r\n // Puede faltar o venir vacío: en ese caso el componente usa sus sugerencias fijas.\r\n Sugerencias?: string[];\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class AsistenteDatosApiService {\r\n // La fija el componente desde su @Input urlConsultar (reemplaza WmChatConfigService.urlConsultar).\r\n public url = '';\r\n\r\n // Mismo origen del JWT que WmSeguridadService.getJWT() en wm-chat: localStorage['WMTKN'],\r\n // descartado si está vencido. Se replica aquí para que el header Authorization sea idéntico\r\n // al del chat original sin depender de un servicio de config externo.\r\n private readonly TOKEN_KEY = 'WMTKN';\r\n private readonly jwtHelper = new JwtHelperService();\r\n\r\n constructor(private http: HttpClient) {}\r\n\r\n consultar(pregunta: string, proveedor?: string): Observable<RespuestaAsistenteDatos> {\r\n const headers = new HttpHeaders({\r\n Authorization: `Bearer ${this.obtenerJWT()}`,\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n });\r\n\r\n return this.http\r\n .post<RespuestaAsistenteDatos>(\r\n this.url,\r\n { Pregunta: pregunta, Proveedor: proveedor },\r\n { headers }\r\n )\r\n .pipe(\r\n catchError((error) => {\r\n return throwError(error.error);\r\n })\r\n );\r\n }\r\n\r\n private obtenerJWT(): string {\r\n const jwt = localStorage.getItem(this.TOKEN_KEY);\r\n\r\n if (jwt) {\r\n try {\r\n return this.jwtHelper.isTokenExpired(jwt) ? null : jwt;\r\n } catch {}\r\n }\r\n return null;\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport * as XLSX from 'xlsx';\r\n\r\n// Exporta/copia el resultado tabular del asistente (\"Pregúntale a tus Datos\"). El resultado ya\r\n// llega como arreglo de objetos (una clave por columna, ver RespuestaAsistenteDatos.Resultado), así\r\n// que no hay que parsear HTML: se recorre directo.\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class TablaExportService {\r\n // Separador del CSV: punto y coma. Excel en configuración regional ES (la de los usuarios WM)\r\n // usa ';' como separador de lista, así que al abrir el .csv las columnas quedan separadas sin\r\n // tener que importar con asistente. El TSV del portapapeles usa TAB, que Excel pega en columnas\r\n // sin depender de la config regional.\r\n private readonly SEPARADOR_CSV = ';';\r\n\r\n columnas(filas: any[]): string[] {\r\n return filas && filas.length ? Object.keys(filas[0]) : [];\r\n }\r\n\r\n private valorCelda(valor: any): string {\r\n if (valor === null || valor === undefined) {\r\n return '';\r\n }\r\n return String(valor);\r\n }\r\n\r\n // TSV para el portapapeles: se pega directo en Excel/Sheets en columnas. Los TAB y saltos de\r\n // línea dentro de una celda se neutralizan a espacio para no romper la cuadrícula al pegar.\r\n private aTsv(filas: any[]): string {\r\n const cols = this.columnas(filas);\r\n const limpiar = (v: string) => v.replace(/\\t/g, ' ').replace(/\\r?\\n/g, ' ');\r\n const encabezado = cols.map(limpiar).join('\\t');\r\n const cuerpo = filas.map((fila) => cols.map((c) => limpiar(this.valorCelda(fila[c]))).join('\\t'));\r\n return [encabezado, ...cuerpo].join('\\n');\r\n }\r\n\r\n async copiar(filas: any[]): Promise<void> {\r\n const tsv = this.aTsv(filas);\r\n\r\n if (navigator.clipboard && navigator.clipboard.writeText) {\r\n await navigator.clipboard.writeText(tsv);\r\n return;\r\n }\r\n\r\n // Fallback para contextos sin Clipboard API (http no seguro, navegadores viejos).\r\n const area = document.createElement('textarea');\r\n area.value = tsv;\r\n area.style.position = 'fixed';\r\n area.style.left = '-9999px';\r\n document.body.appendChild(area);\r\n area.select();\r\n try {\r\n document.execCommand('copy');\r\n } finally {\r\n document.body.removeChild(area);\r\n }\r\n }\r\n\r\n private escaparCsv(valor: string): string {\r\n if (valor.indexOf('\"') >= 0 || valor.indexOf(this.SEPARADOR_CSV) >= 0 || /[\\r\\n]/.test(valor)) {\r\n return '\"' + valor.replace(/\"/g, '\"\"') + '\"';\r\n }\r\n return valor;\r\n }\r\n\r\n descargarCsv(filas: any[], nombreBase: string): void {\r\n const cols = this.columnas(filas);\r\n const lineas = [\r\n cols.map((c) => this.escaparCsv(c)).join(this.SEPARADOR_CSV),\r\n ...filas.map((fila) => cols.map((c) => this.escaparCsv(this.valorCelda(fila[c]))).join(this.SEPARADOR_CSV)),\r\n ];\r\n // BOM UTF-8 () para que Excel muestre tildes y ñ correctamente.\r\n const contenido = '' + lineas.join('\\r\\n');\r\n const blob = new Blob([contenido], { type: 'text/csv;charset=utf-8;' });\r\n this.descargarBlob(blob, nombreBase + '.csv');\r\n }\r\n\r\n descargarXlsx(filas: any[], nombreBase: string): void {\r\n const hoja = XLSX.utils.json_to_sheet(filas);\r\n const libro = XLSX.utils.book_new();\r\n XLSX.utils.book_append_sheet(libro, hoja, 'Datos');\r\n // XLSX.writeFile arma el Blob y dispara la descarga en el navegador.\r\n XLSX.writeFile(libro, nombreBase + '.xlsx');\r\n }\r\n\r\n private descargarBlob(blob: Blob, nombreArchivo: string): void {\r\n const url = URL.createObjectURL(blob);\r\n const enlace = document.createElement('a');\r\n enlace.href = url;\r\n enlace.download = nombreArchivo;\r\n document.body.appendChild(enlace);\r\n enlace.click();\r\n document.body.removeChild(enlace);\r\n setTimeout(() => URL.revokeObjectURL(url));\r\n }\r\n}\r\n","import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';\r\nimport { ReconocimientoVozService } from './reconocimiento-voz.service';\r\nimport { AsistenteDatosApiService } from './asistente-datos-api.service';\r\nimport { TablaExportService } from './tabla-export.service';\r\n\r\nexport interface MensajeAsistenteDatos {\r\n deUsuario: boolean;\r\n texto?: string;\r\n descripcion?: string;\r\n resultado?: any[];\r\n proveedor?: string;\r\n esError?: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'wm-asistente-datos',\r\n templateUrl: './asistente-datos.component.html',\r\n styleUrls: ['./asistente-datos.component.scss'],\r\n})\r\nexport class AsistenteDatosComponent {\r\n @ViewChild('mensajesContainer') private mensajesContainer?: ElementRef<HTMLDivElement>;\r\n\r\n // La apertura/cierre del panel la controla el padre (el menú). El panel solo se renderiza\r\n // cuando `abierto` es true y avisa, vía `cerrarChange`, cuando el usuario toca la X.\r\n @Input() abierto = false;\r\n\r\n // URL del POST de consulta. Se refleja en el api service (propiedad `url`), que es donde se usa.\r\n @Input() set urlConsultar(valor: string) {\r\n if (valor) {\r\n this.asistenteDatosApiService.url = valor;\r\n }\r\n }\r\n\r\n // Idioma para el reconocimiento de voz (Web Speech API).\r\n @Input() idioma = 'es-CO';\r\n\r\n @Output() cerrarChange = new EventEmitter<void>();\r\n\r\n public mensajes: MensajeAsistenteDatos[] = [];\r\n public borrador = '';\r\n // Alterna el alto de la caja del mensaje (compacta ↔ expandida), igual que el \"pedir cambios\"\r\n // del asistente de IA del generador de formularios (ver filasBorrador / onClickExpandirBorrador).\r\n public borradorExpandido = false;\r\n public consultando = false;\r\n // \"Gemini\" o \"Groq\" — mismo selector que el asistente de generación de formularios\r\n // (ver ProveedorIAServicio en el backend).\r\n public proveedorSeleccionado: 'Gemini' | 'Groq' = 'Gemini';\r\n // Dictado por voz (Web Speech API) — sin soporte en Firefox, inconsistente en Safari.\r\n public escuchando = false;\r\n\r\n // Las preguntas sugeridas se muestran con el chat vacío. Tras la primera pregunta (cuando ya\r\n // hay mensajes) quedan plegadas en el botón \"Sugerencias\" que controla este flag, para que el\r\n // área de conversación gane ese espacio; el usuario puede volver a abrirlas. Es solo UI, igual\r\n // con Gemini y con Groq.\r\n public sugerenciasAbiertas = false;\r\n\r\n // Tabla abierta en el modal \"ampliar\" (null = modal cerrado). El panel del chat es angosto y\r\n // recorta las columnas; el modal muestra la misma tabla a todo el ancho de la pantalla.\r\n public tablaAmpliada: any[] | null = null;\r\n public descripcionAmpliada = '';\r\n // Aviso efímero \"Tabla copiada\" tras copiar al portapapeles.\r\n public copiadoAviso = false;\r\n\r\n // Sugerencias FIJAS: preguntas ya verificadas como respondibles (whitelist + contrato de la IA —\r\n // ver ChatConsultaWhitelistServicio/ChatConsultaPromptServicio en el backend). Son el estado\r\n // inicial (chat vacío) y el fallback cuando el backend no devuelve sugerencias contextuales.\r\n public readonly chipsFijos: string[] = [\r\n '¿Cuántos formularios se diligenciaron hoy?',\r\n '¿Cuántos formularios se diligenciaron esta semana?',\r\n 'Muéstrame los últimos 10 formularios diligenciados',\r\n ];\r\n // Sugerencias que se muestran ahora: arrancan en las fijas y, tras cada respuesta, se reemplazan\r\n // por las contextuales que devuelve el backend (Sugerencias); si no vienen, vuelven a las fijas.\r\n public chipsSugeridos: string[] = [...this.chipsFijos];\r\n\r\n constructor(\r\n private asistenteDatosApiService: AsistenteDatosApiService,\r\n private reconocimientoVoz: ReconocimientoVozService,\r\n private tablaExport: TablaExportService\r\n ) {}\r\n\r\n // El padre abre/cierra el panel; aquí solo se avisa que el usuario pidió cerrarlo (botón X).\r\n cerrar(): void {\r\n this.cerrarChange.emit();\r\n }\r\n\r\n // Caja del mensaje compacta (1 fila, como era el chat originalmente) ↔ expandida (6 filas).\r\n // El botón de expandir es el mismo patrón del \"pedir cambios\" del generador.\r\n get filasBorrador(): number {\r\n return this.borradorExpandido ? 6 : 1;\r\n }\r\n\r\n onClickExpandirBorrador(): void {\r\n this.borradorExpandido = !this.borradorExpandido;\r\n }\r\n\r\n get micDisponible(): boolean {\r\n return this.reconocimientoVoz.estaSoportado();\r\n }\r\n\r\n onClickMicrofono(): void {\r\n if (this.escuchando) {\r\n this.reconocimientoVoz.detener();\r\n this.escuchando = false;\r\n return;\r\n }\r\n\r\n if (!this.reconocimientoVoz.estaSoportado()) {\r\n return;\r\n }\r\n\r\n // El resultado del reconocimiento no incluye lo que ya estaba escrito — se guarda antes de\r\n // empezar y se antepone en cada actualización (que llega con la transcripción COMPLETA de\r\n // esta sesión de escucha, no un incremento) para no perder lo que ya había en el campo.\r\n const textoPrevio = this.borrador.trim();\r\n this.escuchando = true;\r\n this.reconocimientoVoz.iniciar(\r\n this.idioma,\r\n (texto) => (this.borrador = textoPrevio ? `${textoPrevio} ${texto}` : texto),\r\n () => (this.escuchando = false)\r\n );\r\n }\r\n\r\n onClickEnviar(textoPreset?: string): void {\r\n const pregunta = (textoPreset ?? this.borrador).trim();\r\n if (!pregunta || this.consultando) {\r\n return;\r\n }\r\n\r\n this.mensajes.push({ deUsuario: true, texto: pregunta });\r\n this.borrador = '';\r\n\r\n // Sin url de consulta no se hace la petición: el usuario ve el mismo error genérico que\r\n // cuando la API falla.\r\n if (!this.asistenteDatosApiService.url) {\r\n this.mensajes.push({\r\n deUsuario: false,\r\n texto: 'No se pudo procesar la consulta.',\r\n esError: true,\r\n });\r\n this.scrollAlFinal();\r\n return;\r\n }\r\n\r\n this.consultando = true;\r\n this.scrollAlFinal();\r\n\r\n this.asistenteDatosApiService.consultar(pregunta, this.proveedorSeleccionado).subscribe({\r\n // El tipo (RespuestaAsistenteDatos) se infiere del Observable: importar la interfaz\r\n // dejaba un import a un símbolo inexistente en el JS de la librería (aviso de rollup).\r\n next: (respuesta) => {\r\n this.consultando = false;\r\n this.mensajes.push({\r\n deUsuario: false,\r\n descripcion: respuesta.Descripcion,\r\n resultado: respuesta.Resultado ?? [],\r\n proveedor: respuesta.Proveedor,\r\n });\r\n this.actualizarSugerencias(respuesta.Sugerencias);\r\n this.scrollAlFinal();\r\n },\r\n error: (error) => {\r\n this.consultando = false;\r\n this.mensajes.push({\r\n deUsuario: false,\r\n texto: error?.Mensaje || 'No se pudo procesar la consulta.',\r\n esError: true,\r\n });\r\n this.scrollAlFinal();\r\n },\r\n });\r\n }\r\n\r\n // Tras cada respuesta, el backend puede devolver sugerencias de seguimiento acotadas al rol. Si\r\n // llegan al menos 2, reemplazan a las que se muestran; si no, se vuelve a las fijas. El chat vacío\r\n // conserva las fijas: este método solo se llama al recibir una respuesta.\r\n private actualizarSugerencias(sugerencias?: string[]): void {\r\n this.chipsSugeridos = sugerencias && sugerencias.length >= 2\r\n ? sugerencias\r\n : [...this.chipsFijos];\r\n }\r\n\r\n // El nuevo mensaje recién se refleja en el DOM después del siguiente ciclo de detección de\r\n // cambios — por eso el scrollTop se ajusta en un setTimeout(0), no inmediatamente después del\r\n // push, para que scrollHeight ya incluya el mensaje agregado.\r\n private scrollAlFinal(): void {\r\n setTimeout(() => {\r\n const elemento = this.mensajesContainer?.nativeElement;\r\n if (elemento) {\r\n elemento.scrollTop = elemento.scrollHeight;\r\n }\r\n });\r\n }\r\n\r\n columnasDe(resultado: any[]): string[] {\r\n return resultado.length ? Object.keys(resultado[0]) : [];\r\n }\r\n\r\n // El backend devuelve un conteo (ChatConsultaIAServicio.EjecutarConteo) como una sola fila con\r\n // una sola columna llamada literalmente \"Resultado\" — se muestra como número grande en vez de\r\n // como tabla de una celda.\r\n esConteo(resultado: any[]): boolean {\r\n return resultado?.length === 1 && Object.keys(resultado[0]).length === 1 && 'Resultado' in resultado[0];\r\n }\r\n\r\n // Listado con una sola columna (ej. una lista de nombres/ids) — se muestra como texto simple\r\n // en vez de una tabla de una sola columna repetida.\r\n esListaSimple(resultado: any[]): boolean {\r\n return resultado?.length > 0 && !this.esConteo(resultado) && this.columnasDe(resultado).length === 1;\r\n }\r\n\r\n textoListaSimple(resultado: any[]): string {\r\n const columna = this.columnasDe(resultado)[0];\r\n return resultado.map((fila) => fila[columna]).join(', ');\r\n }\r\n\r\n // --- Acciones sobre la tabla de resultados (ampliar / copiar / exportar) ---\r\n\r\n ampliar(resultado: any[], descripcion?: string): void {\r\n this.tablaAmpliada = resultado;\r\n this.descripcionAmpliada = descripcion || '';\r\n }\r\n\r\n cerrarAmpliada(): void {\r\n this.tablaAmpliada = null;\r\n this.descripcionAmpliada = '';\r\n }\r\n\r\n async copiar(resultado: any[]): Promise<void> {\r\n try {\r\n await this.tablaExport.copiar(resultado);\r\n this.copiadoAviso = true;\r\n setTimeout(() => (this.copiadoAviso = false), 1800);\r\n } catch {\r\n // Copiar puede fallar por permisos del portapapeles; se ignora en silencio (el usuario\r\n // aún puede ampliar y exportar).\r\n }\r\n }\r\n\r\n exportarCsv(resultado: any[]): void {\r\n this.tablaExport.descargarCsv(resultado, this.nombreArchivo());\r\n }\r\n\r\n exportarXlsx(resultado: any[]): void {\r\n this.tablaExport.descargarXlsx(resultado, this.nombreArchivo());\r\n }\r\n\r\n private nombreArchivo(): string {\r\n const ahora = new Date();\r\n const dos = (n: number) => String(n).padStart(2, '0');\r\n return (\r\n 'asistente-datos-' +\r\n ahora.getFullYear() +\r\n dos(ahora.getMonth() + 1) +\r\n dos(ahora.getDate()) +\r\n '-' +\r\n dos(ahora.getHours()) +\r\n dos(ahora.getMinutes())\r\n );\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\n\r\nimport { MatToolbarModule } from '@angular/material/toolbar';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatSidenavModule} from '@angular/material/sidenav';\r\nimport { MatListModule } from '@angular/material/list';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatMenuModule } from '@angular/material/menu';\r\nimport { MatTableModule } from '@angular/material/table';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatRippleModule } from \"@angular/material/core\";\r\nimport { FormsModule } from '@angular/forms';\r\n\r\nimport { WmMenuComponent } from './wm-menu/wm-menu.component';\r\nimport { AsistenteDatosComponent } from './wm-menu/asistente-datos/asistente-datos.component';\r\nimport { HttpClientModule } from '@angular/common/http';\r\nimport { BrowserModule } from '@angular/platform-browser';\r\nimport { JwtModule } from '@auth0/angular-jwt';\r\n\r\n\r\n@NgModule({\r\n declarations: [WmMenuComponent, AsistenteDatosComponent],\r\n imports: [\r\n BrowserModule,\r\n FormsModule,\r\n MatToolbarModule,\r\n MatSidenavModule,\r\n MatListModule,\r\n MatButtonModule,\r\n MatIconModule,\r\n MatMenuModule,\r\n MatTableModule,\r\n MatTooltipModule,\r\n MatRippleModule,\r\n HttpClientModule,\r\n JwtModule\r\n ],\r\n exports: [WmMenuComponent]\r\n})\r\nexport class WmMenuModule { }\r\n","/*\r\n * Public API Surface of wm-menu\r\n */\r\n\r\nexport * from './lib/wm-menu/wm-menu.component';\r\nexport * from './lib/wm-menu/services/wm-menu-servicio.service';\r\nexport * from './lib/wm-menu/services/wm-menu-alerta-panico.service';\r\nexport * from './lib/wm-menu.module';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n\nexport {AsistenteDatosApiService as ɵc} from './lib/wm-menu/asistente-datos/asistente-datos-api.service';\nexport {AsistenteDatosComponent as ɵb} from './lib/wm-menu/asistente-datos/asistente-datos.component';\nexport {ReconocimientoVozService as ɵd} from './lib/wm-menu/asistente-datos/reconocimiento-voz.service';\nexport {TablaExportService as ɵe} from './lib/wm-menu/asistente-datos/tabla-export.service';\nexport {WmMenuFuenteIconosService as ɵa} from './lib/wm-menu/services/wm-menu-fuente-iconos.service';"],"names":["XLSX.utils","XLSX.writeFile"],"mappings":"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"}
package/fesm5/wm-menu.js CHANGED
@@ -744,20 +744,28 @@ var AsistenteDatosComponent = /** @class */ (function () {
744
744
  this.proveedorSeleccionado = 'Gemini';
745
745
  // Dictado por voz (Web Speech API) — sin soporte en Firefox, inconsistente en Safari.
746
746
  this.escuchando = false;
747
+ // Las preguntas sugeridas se muestran con el chat vacío. Tras la primera pregunta (cuando ya
748
+ // hay mensajes) quedan plegadas en el botón "Sugerencias" que controla este flag, para que el
749
+ // área de conversación gane ese espacio; el usuario puede volver a abrirlas. Es solo UI, igual
750
+ // con Gemini y con Groq.
751
+ this.sugerenciasAbiertas = false;
747
752
  // Tabla abierta en el modal "ampliar" (null = modal cerrado). El panel del chat es angosto y
748
753
  // recorta las columnas; el modal muestra la misma tabla a todo el ancho de la pantalla.
749
754
  this.tablaAmpliada = null;
750
755
  this.descripcionAmpliada = '';
751
756
  // Aviso efímero "Tabla copiada" tras copiar al portapapeles.
752
757
  this.copiadoAviso = false;
753
- // Preguntas ya verificadas como respondibles hoy (whitelist + contrato de la IA — ver
754
- // ChatConsultaWhitelistServicio/ChatConsultaPromptServicio en el backend), mostradas como chips
755
- // de sugerencia en el estado vacío del chat.
756
- this.chipsSugeridos = [
758
+ // Sugerencias FIJAS: preguntas ya verificadas como respondibles (whitelist + contrato de la IA —
759
+ // ver ChatConsultaWhitelistServicio/ChatConsultaPromptServicio en el backend). Son el estado
760
+ // inicial (chat vacío) y el fallback cuando el backend no devuelve sugerencias contextuales.
761
+ this.chipsFijos = [
757
762
  '¿Cuántos formularios se diligenciaron hoy?',
758
763
  '¿Cuántos formularios se diligenciaron esta semana?',
759
764
  'Muéstrame los últimos 10 formularios diligenciados',
760
765
  ];
766
+ // Sugerencias que se muestran ahora: arrancan en las fijas y, tras cada respuesta, se reemplazan
767
+ // por las contextuales que devuelve el backend (Sugerencias); si no vienen, vuelven a las fijas.
768
+ this.chipsSugeridos = __spread(this.chipsFijos);
761
769
  }
762
770
  Object.defineProperty(AsistenteDatosComponent.prototype, "urlConsultar", {
763
771
  // URL del POST de consulta. Se refleja en el api service (propiedad `url`), que es donde se usa.
@@ -842,6 +850,7 @@ var AsistenteDatosComponent = /** @class */ (function () {
842
850
  resultado: (_a = respuesta.Resultado, (_a !== null && _a !== void 0 ? _a : [])),
843
851
  proveedor: respuesta.Proveedor,
844
852
  });
853
+ _this.actualizarSugerencias(respuesta.Sugerencias);
845
854
  _this.scrollAlFinal();
846
855
  },
847
856
  error: function (error) {
@@ -856,6 +865,14 @@ var AsistenteDatosComponent = /** @class */ (function () {
856
865
  },
857
866
  });
858
867
  };
868
+ // Tras cada respuesta, el backend puede devolver sugerencias de seguimiento acotadas al rol. Si
869
+ // llegan al menos 2, reemplazan a las que se muestran; si no, se vuelve a las fijas. El chat vacío
870
+ // conserva las fijas: este método solo se llama al recibir una respuesta.
871
+ AsistenteDatosComponent.prototype.actualizarSugerencias = function (sugerencias) {
872
+ this.chipsSugeridos = sugerencias && sugerencias.length >= 2
873
+ ? sugerencias
874
+ : __spread(this.chipsFijos);
875
+ };
859
876
  // El nuevo mensaje recién se refleja en el DOM después del siguiente ciclo de detección de
860
877
  // cambios — por eso el scrollTop se ajusta en un setTimeout(0), no inmediatamente después del
861
878
  // push, para que scrollHeight ya incluya el mensaje agregado.
@@ -960,8 +977,8 @@ var AsistenteDatosComponent = /** @class */ (function () {
960
977
  AsistenteDatosComponent = __decorate([
961
978
  Component({
962
979
  selector: 'wm-asistente-datos',
963
- template: "<!-- Panel (abierto) -->\r\n<div class=\"chat-ia-panel\" *ngIf=\"abierto\">\r\n <div class=\"chat-ia-header\">\r\n <div class=\"chat-ia-header-info\">\r\n <div class=\"chat-ia-header-icono\">\r\n <svg width=\"17\" height=\"17\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"1.8\">\r\n <path d=\"M4 5h16v10H9l-4 4V15H4z\"></path>\r\n </svg>\r\n </div>\r\n <div>\r\n <div class=\"chat-ia-titulo\">Preg\u00FAntale a tus Datos</div>\r\n <div class=\"chat-ia-subtitulo\">Consulta tus reportes en lenguaje natural</div>\r\n </div>\r\n </div>\r\n <div class=\"chat-ia-cerrar\" (click)=\"cerrar()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" stroke=\"#fff\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\">\r\n <path d=\"M6 6l12 12M18 6L6 18\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-ia-mensajes\" #mensajesContainer>\r\n <div class=\"chat-ia-bienvenida-texto\">Hola, soy tu asistente de datos de Snap Forms. Preg\u00FAntame lo que quieras saber sobre tu operaci\u00F3n.</div>\r\n\r\n <div class=\"chat-ia-mensaje\" *ngFor=\"let mensaje of mensajes\" [class.chat-ia-mensaje-usuario]=\"mensaje.deUsuario\">\r\n <div class=\"chat-ia-burbuja\" [class.chat-ia-burbuja-error]=\"mensaje.esError\">\r\n <span *ngIf=\"mensaje.texto\">{{ mensaje.texto }}</span>\r\n\r\n <ng-container *ngIf=\"mensaje.resultado\">\r\n <div class=\"chat-ia-descripcion\" *ngIf=\"mensaje.descripcion\">{{ mensaje.descripcion }}</div>\r\n\r\n <div class=\"chat-ia-sin-resultados\" *ngIf=\"mensaje.resultado.length === 0\">La consulta no encontr\u00F3 resultados.</div>\r\n\r\n <div class=\"chat-ia-stat\" *ngIf=\"esConteo(mensaje.resultado)\">\r\n <div class=\"chat-ia-stat-valor\">{{ mensaje.resultado[0].Resultado | number }}</div>\r\n </div>\r\n\r\n <div class=\"chat-ia-lista-simple\" *ngIf=\"esListaSimple(mensaje.resultado)\">{{ textoListaSimple(mensaje.resultado) }}</div>\r\n\r\n <div class=\"chat-ia-tabla-bloque\" *ngIf=\"mensaje.resultado.length > 0 && !esConteo(mensaje.resultado) && !esListaSimple(mensaje.resultado)\">\r\n <div class=\"chat-ia-tabla-acciones\">\r\n <button type=\"button\" class=\"chat-ia-accion\" matTooltip=\"Ampliar\"\r\n (click)=\"ampliar(mensaje.resultado, mensaje.descripcion)\">\r\n <mat-icon>open_in_full</mat-icon>\r\n </button>\r\n <button type=\"button\" class=\"chat-ia-accion\" matTooltip=\"Copiar\"\r\n (click)=\"copiar(mensaje.resultado)\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button type=\"button\" class=\"chat-ia-accion\" matTooltip=\"Exportar\"\r\n [matMenuTriggerFor]=\"menuExport\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #menuExport=\"matMenu\" class=\"menu-export-chat-ia\">\r\n <button mat-menu-item type=\"button\" (click)=\"exportarCsv(mensaje.resultado)\">CSV (.csv)</button>\r\n <button mat-menu-item type=\"button\" (click)=\"exportarXlsx(mensaje.resultado)\">Excel (.xlsx)</button>\r\n </mat-menu>\r\n </div>\r\n <div class=\"chat-ia-tabla-resultado\">\r\n <table mat-table [dataSource]=\"mensaje.resultado\">\r\n <ng-container *ngFor=\"let columna of columnasDe(mensaje.resultado)\" [matColumnDef]=\"columna\">\r\n <th mat-header-cell *matHeaderCellDef>{{ columna }}</th>\r\n <td mat-cell *matCellDef=\"let fila\">{{ fila[columna] }}</td>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\"columnasDe(mensaje.resultado)\"></tr>\r\n <tr mat-row *matRowDef=\"let fila; columns: columnasDe(mensaje.resultado);\"></tr>\r\n </table>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-ia-pensando\" *ngIf=\"consultando\">\r\n <span class=\"chat-ia-dot\"></span><span class=\"chat-ia-dot\"></span><span class=\"chat-ia-dot\"></span>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chips-chat-ia\">\r\n <span class=\"chip-chat-ia\" *ngFor=\"let chip of chipsSugeridos\"\r\n (click)=\"onClickEnviar(chip)\">{{ chip }}</span>\r\n </div>\r\n\r\n <div class=\"chat-ia-entrada\">\r\n <div class=\"chat-ia-caja-entrada\">\r\n <mat-icon fontSet=\"wm-menu-iconos\" class=\"chat-ia-expandir\" (click)=\"onClickExpandirBorrador()\">{{ borradorExpandido ? 'close_fullscreen' : 'open_in_full' }}</mat-icon>\r\n <textarea [rows]=\"filasBorrador\" [(ngModel)]=\"borrador\" (keydown.enter)=\"$event.preventDefault(); onClickEnviar()\"\r\n [class.chat-ia-textarea-expandido]=\"borradorExpandido\"\r\n placeholder=\"Escribe tu pregunta...\"></textarea>\r\n <div class=\"chat-ia-pie-entrada\">\r\n <button class=\"chat-ia-selector-modelo\" [matMenuTriggerFor]=\"menuModeloChatIA\" type=\"button\">\r\n <span *ngIf=\"proveedorSeleccionado === 'Gemini'\">Gemini</span>\r\n <span *ngIf=\"proveedorSeleccionado === 'Groq'\">Groq</span>\r\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"></path>\r\n </svg>\r\n </button>\r\n <button class=\"chat-ia-microfono\" [class.chat-ia-microfono-activo]=\"escuchando\" *ngIf=\"micDisponible\"\r\n (click)=\"onClickMicrofono()\" type=\"button\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\"></path>\r\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"></path>\r\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\"></line>\r\n </svg>\r\n </button>\r\n <button class=\"chat-ia-enviar\" [disabled]=\"!borrador.trim() || consultando\" (click)=\"onClickEnviar()\" type=\"button\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 19V6\"></path>\r\n <path d=\"M5 13l7-7 7 7\"></path>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<mat-menu #menuModeloChatIA=\"matMenu\" class=\"menu-modelo-chat-ia\">\r\n <button mat-menu-item [class.opcion-activa]=\"proveedorSeleccionado === 'Gemini'\"\r\n (click)=\"proveedorSeleccionado = 'Gemini'\">\r\n <span>Gemini</span>\r\n <svg *ngIf=\"proveedorSeleccionado === 'Gemini'\" class=\"chat-ia-check\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M20 6L9 17l-5-5\"></path>\r\n </svg>\r\n </button>\r\n <button mat-menu-item [class.opcion-activa]=\"proveedorSeleccionado === 'Groq'\"\r\n (click)=\"proveedorSeleccionado = 'Groq'\">\r\n <span>Groq</span>\r\n <svg *ngIf=\"proveedorSeleccionado === 'Groq'\" class=\"chat-ia-check\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M20 6L9 17l-5-5\"></path>\r\n </svg>\r\n </button>\r\n</mat-menu>\r\n\r\n<!-- Modal \"ampliar\": muestra la tabla a todo el ancho de la pantalla (el panel la recorta). Overlay\r\n propio (no CDK) porque el componente se monta como web-component y el overlay de CDK queda fuera\r\n de su contexto de estilos. -->\r\n<div class=\"chat-ia-modal-overlay\" *ngIf=\"tablaAmpliada\" (click)=\"cerrarAmpliada()\">\r\n <div class=\"chat-ia-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"chat-ia-modal-header\">\r\n <div class=\"chat-ia-modal-titulo\">{{ descripcionAmpliada || 'Resultados' }}</div>\r\n <div class=\"chat-ia-modal-acciones\">\r\n <button type=\"button\" class=\"chat-ia-accion chat-ia-accion-clara\" matTooltip=\"Copiar\"\r\n (click)=\"copiar(tablaAmpliada)\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button type=\"button\" class=\"chat-ia-accion chat-ia-accion-clara\" matTooltip=\"Exportar\"\r\n [matMenuTriggerFor]=\"menuExportModal\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #menuExportModal=\"matMenu\" class=\"menu-export-chat-ia\">\r\n <button mat-menu-item type=\"button\" (click)=\"exportarCsv(tablaAmpliada)\">CSV (.csv)</button>\r\n <button mat-menu-item type=\"button\" (click)=\"exportarXlsx(tablaAmpliada)\">Excel (.xlsx)</button>\r\n </mat-menu>\r\n <button type=\"button\" class=\"chat-ia-accion chat-ia-accion-clara\" matTooltip=\"Cerrar\"\r\n (click)=\"cerrarAmpliada()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"chat-ia-modal-tabla\">\r\n <table mat-table [dataSource]=\"tablaAmpliada\">\r\n <ng-container *ngFor=\"let columna of columnasDe(tablaAmpliada)\" [matColumnDef]=\"columna\">\r\n <th mat-header-cell *matHeaderCellDef>{{ columna }}</th>\r\n <td mat-cell *matCellDef=\"let fila\">{{ fila[columna] }}</td>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\"columnasDe(tablaAmpliada)\"></tr>\r\n <tr mat-row *matRowDef=\"let fila; columns: columnasDe(tablaAmpliada);\"></tr>\r\n </table>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Aviso ef\u00EDmero tras copiar al portapapeles. -->\r\n<div class=\"chat-ia-copiado-aviso\" *ngIf=\"copiadoAviso\">Tabla copiada</div>\r\n",
964
- styles: [":host{position:fixed;right:32px;bottom:32px;z-index:1000;font-family:Roboto,sans-serif}.chat-ia-panel{width:450px;height:650px;max-width:calc(100vw - 48px);max-height:calc(100vh - 96px);background:#fff;border-radius:18px;box-shadow:0 24px 60px rgba(20,25,30,.28);display:flex;flex-direction:column;overflow:hidden}.chat-ia-header{background:linear-gradient(135deg,#7c5ce0,#5f42bd);padding:16px 18px;display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.chat-ia-header-info{display:flex;align-items:center;gap:10px;min-width:0}.chat-ia-header-icono{width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.22);display:flex;align-items:center;justify-content:center;flex:none}.chat-ia-titulo{color:#fff;font-size:14px;font-weight:500}.chat-ia-subtitulo{color:rgba(255,255,255,.75);font-size:11px;margin-top:1px}.chat-ia-cerrar{width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:.85;flex:none}.chat-ia-cerrar:hover{opacity:1}.chat-ia-mensajes{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:12px;padding:16px;background:#fbfafc}.chat-ia-mensaje{display:flex}.chat-ia-mensaje .chat-ia-burbuja{max-width:88%;background:#f2eefb;color:#26313a;border-radius:14px 14px 14px 3px;padding:10px 13px;font-size:13px;line-height:1.5}.chat-ia-mensaje .chat-ia-burbuja-error{background:#fdecea;color:#7a1f14}.chat-ia-mensaje.chat-ia-mensaje-usuario{justify-content:flex-end}.chat-ia-mensaje.chat-ia-mensaje-usuario .chat-ia-burbuja{background:#7c5ce0;color:#fff;border-radius:14px 14px 3px}.chat-ia-bienvenida-texto{align-self:flex-start;max-width:88%;background:#f2eefb;color:#26313a;border-radius:14px 14px 14px 3px;padding:10px 13px;font-size:13px;line-height:1.5}.chips-chat-ia{flex:none;display:flex;flex-wrap:wrap;gap:6px;padding:0 16px 10px}.chip-chat-ia{border:1px solid #e7e2f5;background:#f2eefb;color:#5f42bd;border-radius:14px;padding:5px 10px;font-size:11px;cursor:pointer}.chip-chat-ia:hover{background:#e7ddfa}.chat-ia-descripcion{font-size:13px;line-height:1.5;margin-bottom:6px}.chat-ia-sin-resultados{color:#5a5a5a;font-style:italic}.chat-ia-stat{margin-top:4px}.chat-ia-stat-valor{font-size:30px;font-weight:600;color:#5f42bd;line-height:1.15;font-variant-numeric:proportional-nums}.chat-ia-lista-simple,.chat-ia-tabla-bloque{margin-top:4px;background:#fff;border-radius:10px;padding:8px 10px}.chat-ia-lista-simple{font-size:13px;line-height:1.5}.chat-ia-tabla-acciones{display:flex;justify-content:flex-end;align-items:center;gap:2px;margin-bottom:2px}.chat-ia-accion{width:26px;height:26px;border:none;background:0 0;color:#6b6478;border-radius:7px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:none}.chat-ia-accion:hover{background:#f2eefb}.chat-ia-accion .mat-icon{font-size:17px;width:17px;height:17px;line-height:17px}.chat-ia-accion.chat-ia-accion-clara{color:rgba(255,255,255,.9)}.chat-ia-accion.chat-ia-accion-clara:hover{background:rgba(255,255,255,.18);color:#fff}.chat-ia-tabla-resultado{overflow-x:auto;max-width:100%}.chat-ia-tabla-resultado table{font-size:12px;background:0 0}.chat-ia-tabla-resultado th.mat-header-cell{color:#6b6478;font-weight:600;padding:0 14px 5px 0;border-bottom:1px solid #f0edf7;white-space:nowrap}.chat-ia-tabla-resultado td.mat-cell{padding:7px 14px 0 0;white-space:nowrap;font-variant-numeric:tabular-nums}.chat-ia-pensando{align-self:flex-start;background:#f2eefb;padding:12px 16px;border-radius:14px 14px 14px 3px;display:flex;gap:5px;flex-shrink:0}.chat-ia-dot{width:6px;height:6px;border-radius:50%;background:#9a93ae;-webkit-animation:1.1s ease-in-out infinite chatIaBlink;animation:1.1s ease-in-out infinite chatIaBlink}.chat-ia-dot:nth-child(2){-webkit-animation-delay:.15s;animation-delay:.15s}.chat-ia-dot:nth-child(3){-webkit-animation-delay:.3s;animation-delay:.3s}@-webkit-keyframes chatIaBlink{0%,100%,80%{opacity:.25}40%{opacity:1}}@keyframes chatIaBlink{0%,100%,80%{opacity:.25}40%{opacity:1}}.chat-ia-entrada{padding:10px 14px 14px;border-top:1px solid #e9f2ee;flex-shrink:0}.chat-ia-caja-entrada{position:relative;background:#f2f7f5;border:1px solid #e6efea;border-radius:18px;padding:10px 12px 8px}.chat-ia-caja-entrada textarea{border:none;outline:0;background:0 0;width:100%;font:inherit;font-size:13.5px;color:#26313a;resize:none;line-height:1.45;max-height:110px;overflow-y:auto;display:block;padding:0 28px 0 0}.chat-ia-caja-entrada textarea.chat-ia-textarea-expandido{max-height:160px}.chat-ia-caja-entrada textarea::-webkit-input-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea::-moz-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea:-ms-input-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea::-ms-input-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea::placeholder{color:#9a93ae}.chat-ia-expandir{position:absolute;top:8px;right:10px;font-size:17px;height:17px;width:17px;color:#9a9a9a;cursor:pointer}.chat-ia-pie-entrada{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:8px}.chat-ia-selector-modelo{display:inline-flex;align-items:center;gap:4px;border:none;background:0 0;color:#4e5d57;border-radius:14px;padding:5px 9px;font-size:11.5px;font-weight:600;cursor:pointer}.chat-ia-enviar{width:32px;height:32px;border-radius:50%;border:none;background:#7c5ce0;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none}.chat-ia-enviar:disabled{background:#dce6e1;color:#a9bab3;cursor:default}.chat-ia-microfono{width:28px;height:28px;border-radius:50%;border:none;background:0 0;color:#6b6478;display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none}.chat-ia-microfono:hover{background:#f2eefb}.chat-ia-microfono.chat-ia-microfono-activo{color:#fff;background:#e05a5a;-webkit-animation:1.1s ease-in-out infinite chatIaBlink;animation:1.1s ease-in-out infinite chatIaBlink}::ng-deep .mat-menu-panel.menu-modelo-chat-ia{min-width:132px;border:1px solid #e6efea;border-radius:10px;box-shadow:0 12px 26px rgba(20,25,30,.16)}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-content{padding:4px}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-item{display:flex;align-items:center;justify-content:space-between;gap:8px;height:auto;line-height:normal;padding:7px 10px;font-size:12px;color:#26313a;border-radius:7px}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-item.opcion-activa{background:#f2f7f5}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-item .chat-ia-check{color:#7c5ce0}.chat-ia-modal-overlay{position:fixed;inset:0;background:rgba(20,25,30,.5);display:flex;align-items:center;justify-content:center;padding:24px;z-index:1100}.chat-ia-modal{background:#fff;border-radius:16px;box-shadow:0 24px 60px rgba(20,25,30,.32);width:auto;max-width:92vw;max-height:86vh;display:flex;flex-direction:column;overflow:hidden}.chat-ia-modal-header{background:linear-gradient(135deg,#7c5ce0,#5f42bd);padding:12px 16px;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-shrink:0}.chat-ia-modal-titulo{color:#fff;font-size:14px;font-weight:500;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-ia-modal-acciones{display:flex;align-items:center;gap:2px;flex:none}.chat-ia-modal-tabla{flex:1;min-height:0;overflow:auto;padding:10px 16px 16px}.chat-ia-modal-tabla table{font-size:13px;background:0 0;width:100%}.chat-ia-modal-tabla th.mat-header-cell{color:#6b6478;font-weight:600;padding:0 18px 8px 0;border-bottom:1px solid #f0edf7;white-space:nowrap}.chat-ia-modal-tabla td.mat-cell{padding:9px 18px 9px 0;white-space:nowrap;color:#26313a;border-bottom:1px solid #f6f4fb;font-variant-numeric:tabular-nums}.chat-ia-copiado-aviso{position:fixed;top:24px;left:50%;transform:translateX(-50%);background:#26313a;color:#fff;font-size:12.5px;padding:8px 16px;border-radius:20px;box-shadow:0 8px 20px rgba(20,25,30,.25);z-index:1200;-webkit-animation:.15s ease-out chatIaAvisoEntrada;animation:.15s ease-out chatIaAvisoEntrada}@-webkit-keyframes chatIaAvisoEntrada{from{opacity:0;transform:translate(-50%,-6px)}to{opacity:1;transform:translate(-50%,0)}}@keyframes chatIaAvisoEntrada{from{opacity:0;transform:translate(-50%,-6px)}to{opacity:1;transform:translate(-50%,0)}}::ng-deep .mat-menu-panel.menu-export-chat-ia{min-width:132px;border:1px solid #e6efea;border-radius:10px;box-shadow:0 12px 26px rgba(20,25,30,.16)}::ng-deep .mat-menu-panel.menu-export-chat-ia .mat-menu-content{padding:4px}::ng-deep .mat-menu-panel.menu-export-chat-ia .mat-menu-item{height:auto;line-height:normal;padding:8px 12px;font-size:12px;color:#26313a;border-radius:7px}::ng-deep .mat-menu-panel.menu-export-chat-ia .mat-menu-item:hover{background:#f2f7f5}"]
980
+ template: "<!-- Panel (abierto) -->\r\n<div class=\"chat-ia-panel\" *ngIf=\"abierto\">\r\n <div class=\"chat-ia-header\">\r\n <div class=\"chat-ia-header-info\">\r\n <div class=\"chat-ia-header-icono\">\r\n <svg width=\"17\" height=\"17\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#fff\" stroke-width=\"1.8\">\r\n <path d=\"M4 5h16v10H9l-4 4V15H4z\"></path>\r\n </svg>\r\n </div>\r\n <div>\r\n <div class=\"chat-ia-titulo\">Preg\u00FAntale a tus Datos</div>\r\n <div class=\"chat-ia-subtitulo\">Consulta tus reportes en lenguaje natural</div>\r\n </div>\r\n </div>\r\n <div class=\"chat-ia-cerrar\" (click)=\"cerrar()\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" stroke=\"#fff\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\">\r\n <path d=\"M6 6l12 12M18 6L6 18\"></path>\r\n </svg>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-ia-mensajes\" #mensajesContainer>\r\n <div class=\"chat-ia-bienvenida-texto\">Hola, soy tu asistente de datos de Snap Forms. Preg\u00FAntame lo que quieras saber sobre tu operaci\u00F3n.</div>\r\n\r\n <div class=\"chat-ia-mensaje\" *ngFor=\"let mensaje of mensajes\" [class.chat-ia-mensaje-usuario]=\"mensaje.deUsuario\">\r\n <div class=\"chat-ia-burbuja\" [class.chat-ia-burbuja-error]=\"mensaje.esError\">\r\n <span *ngIf=\"mensaje.texto\">{{ mensaje.texto }}</span>\r\n\r\n <ng-container *ngIf=\"mensaje.resultado\">\r\n <div class=\"chat-ia-descripcion\" *ngIf=\"mensaje.descripcion\">{{ mensaje.descripcion }}</div>\r\n\r\n <div class=\"chat-ia-sin-resultados\" *ngIf=\"mensaje.resultado.length === 0\">La consulta no encontr\u00F3 resultados.</div>\r\n\r\n <div class=\"chat-ia-stat\" *ngIf=\"esConteo(mensaje.resultado)\">\r\n <div class=\"chat-ia-stat-valor\">{{ mensaje.resultado[0].Resultado | number }}</div>\r\n </div>\r\n\r\n <div class=\"chat-ia-lista-simple\" *ngIf=\"esListaSimple(mensaje.resultado)\">{{ textoListaSimple(mensaje.resultado) }}</div>\r\n\r\n <div class=\"chat-ia-tabla-bloque\" *ngIf=\"mensaje.resultado.length > 0 && !esConteo(mensaje.resultado) && !esListaSimple(mensaje.resultado)\">\r\n <div class=\"chat-ia-tabla-acciones\">\r\n <button type=\"button\" class=\"chat-ia-accion\" matTooltip=\"Ampliar\"\r\n (click)=\"ampliar(mensaje.resultado, mensaje.descripcion)\">\r\n <mat-icon>open_in_full</mat-icon>\r\n </button>\r\n <button type=\"button\" class=\"chat-ia-accion\" matTooltip=\"Copiar\"\r\n (click)=\"copiar(mensaje.resultado)\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button type=\"button\" class=\"chat-ia-accion\" matTooltip=\"Exportar\"\r\n [matMenuTriggerFor]=\"menuExport\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #menuExport=\"matMenu\" class=\"menu-export-chat-ia\">\r\n <button mat-menu-item type=\"button\" (click)=\"exportarCsv(mensaje.resultado)\">CSV (.csv)</button>\r\n <button mat-menu-item type=\"button\" (click)=\"exportarXlsx(mensaje.resultado)\">Excel (.xlsx)</button>\r\n </mat-menu>\r\n </div>\r\n <div class=\"chat-ia-tabla-resultado\">\r\n <table mat-table [dataSource]=\"mensaje.resultado\">\r\n <ng-container *ngFor=\"let columna of columnasDe(mensaje.resultado)\" [matColumnDef]=\"columna\">\r\n <th mat-header-cell *matHeaderCellDef>{{ columna }}</th>\r\n <td mat-cell *matCellDef=\"let fila\">{{ fila[columna] }}</td>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\"columnasDe(mensaje.resultado)\"></tr>\r\n <tr mat-row *matRowDef=\"let fila; columns: columnasDe(mensaje.resultado);\"></tr>\r\n </table>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"chat-ia-pensando\" *ngIf=\"consultando\">\r\n <span class=\"chat-ia-dot\"></span><span class=\"chat-ia-dot\"></span><span class=\"chat-ia-dot\"></span>\r\n </div>\r\n </div>\r\n\r\n <!-- Sugerencias: con el chat vac\u00EDo se muestran. Tras la primera pregunta (ya hay mensajes)\r\n quedan plegadas en el bot\u00F3n \"Sugerencias\", que las abre/cierra; al estar plegadas, el \u00E1rea\r\n de conversaci\u00F3n gana ese espacio. -->\r\n <button type=\"button\" class=\"chip-chat-ia-toggle\" *ngIf=\"mensajes.length > 0\"\r\n (click)=\"sugerenciasAbiertas = !sugerenciasAbiertas\">\r\n <svg class=\"chip-chat-ia-toggle-bombilla\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M9 18h6\"></path>\r\n <path d=\"M10 22h4\"></path>\r\n <path d=\"M12 2a7 7 0 0 0-4 12.7c.6.5 1 1.3 1 2.1V18h6v-1.2c0-.8.4-1.6 1-2.1A7 7 0 0 0 12 2z\"></path>\r\n </svg>\r\n <span>Sugerencias</span>\r\n <svg class=\"chip-chat-ia-toggle-chevron\" [class.abierto]=\"sugerenciasAbiertas\" width=\"11\" height=\"11\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"></path>\r\n </svg>\r\n </button>\r\n <div class=\"chips-chat-ia\" *ngIf=\"mensajes.length === 0 || sugerenciasAbiertas\">\r\n <span class=\"chip-chat-ia\" *ngFor=\"let chip of chipsSugeridos\"\r\n (click)=\"onClickEnviar(chip)\">{{ chip }}</span>\r\n </div>\r\n\r\n <div class=\"chat-ia-entrada\">\r\n <div class=\"chat-ia-caja-entrada\">\r\n <mat-icon fontSet=\"wm-menu-iconos\" class=\"chat-ia-expandir\" (click)=\"onClickExpandirBorrador()\">{{ borradorExpandido ? 'close_fullscreen' : 'open_in_full' }}</mat-icon>\r\n <textarea [rows]=\"filasBorrador\" [(ngModel)]=\"borrador\" (keydown.enter)=\"$event.preventDefault(); onClickEnviar()\"\r\n [class.chat-ia-textarea-expandido]=\"borradorExpandido\"\r\n placeholder=\"Escribe tu pregunta...\"></textarea>\r\n <div class=\"chat-ia-pie-entrada\">\r\n <button class=\"chat-ia-selector-modelo\" [matMenuTriggerFor]=\"menuModeloChatIA\" type=\"button\">\r\n <span *ngIf=\"proveedorSeleccionado === 'Gemini'\">Gemini</span>\r\n <span *ngIf=\"proveedorSeleccionado === 'Groq'\">Groq</span>\r\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.6\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M6 9l6 6 6-6\"></path>\r\n </svg>\r\n </button>\r\n <button class=\"chat-ia-microfono\" [class.chat-ia-microfono-activo]=\"escuchando\" *ngIf=\"micDisponible\"\r\n (click)=\"onClickMicrofono()\" type=\"button\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z\"></path>\r\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\"></path>\r\n <line x1=\"12\" y1=\"19\" x2=\"12\" y2=\"23\"></line>\r\n </svg>\r\n </button>\r\n <button class=\"chat-ia-enviar\" [disabled]=\"!borrador.trim() || consultando\" (click)=\"onClickEnviar()\" type=\"button\">\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M12 19V6\"></path>\r\n <path d=\"M5 13l7-7 7 7\"></path>\r\n </svg>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<mat-menu #menuModeloChatIA=\"matMenu\" class=\"menu-modelo-chat-ia\">\r\n <button mat-menu-item [class.opcion-activa]=\"proveedorSeleccionado === 'Gemini'\"\r\n (click)=\"proveedorSeleccionado = 'Gemini'\">\r\n <span>Gemini</span>\r\n <svg *ngIf=\"proveedorSeleccionado === 'Gemini'\" class=\"chat-ia-check\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M20 6L9 17l-5-5\"></path>\r\n </svg>\r\n </button>\r\n <button mat-menu-item [class.opcion-activa]=\"proveedorSeleccionado === 'Groq'\"\r\n (click)=\"proveedorSeleccionado = 'Groq'\">\r\n <span>Groq</span>\r\n <svg *ngIf=\"proveedorSeleccionado === 'Groq'\" class=\"chat-ia-check\" width=\"13\" height=\"13\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <path d=\"M20 6L9 17l-5-5\"></path>\r\n </svg>\r\n </button>\r\n</mat-menu>\r\n\r\n<!-- Modal \"ampliar\": muestra la tabla a todo el ancho de la pantalla (el panel la recorta). Overlay\r\n propio (no CDK) porque el componente se monta como web-component y el overlay de CDK queda fuera\r\n de su contexto de estilos. -->\r\n<div class=\"chat-ia-modal-overlay\" *ngIf=\"tablaAmpliada\" (click)=\"cerrarAmpliada()\">\r\n <div class=\"chat-ia-modal\" (click)=\"$event.stopPropagation()\">\r\n <div class=\"chat-ia-modal-header\">\r\n <div class=\"chat-ia-modal-titulo\">{{ descripcionAmpliada || 'Resultados' }}</div>\r\n <div class=\"chat-ia-modal-acciones\">\r\n <button type=\"button\" class=\"chat-ia-accion chat-ia-accion-clara\" matTooltip=\"Copiar\"\r\n (click)=\"copiar(tablaAmpliada)\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button type=\"button\" class=\"chat-ia-accion chat-ia-accion-clara\" matTooltip=\"Exportar\"\r\n [matMenuTriggerFor]=\"menuExportModal\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n <mat-menu #menuExportModal=\"matMenu\" class=\"menu-export-chat-ia\">\r\n <button mat-menu-item type=\"button\" (click)=\"exportarCsv(tablaAmpliada)\">CSV (.csv)</button>\r\n <button mat-menu-item type=\"button\" (click)=\"exportarXlsx(tablaAmpliada)\">Excel (.xlsx)</button>\r\n </mat-menu>\r\n <button type=\"button\" class=\"chat-ia-accion chat-ia-accion-clara\" matTooltip=\"Cerrar\"\r\n (click)=\"cerrarAmpliada()\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"chat-ia-modal-tabla\">\r\n <table mat-table [dataSource]=\"tablaAmpliada\">\r\n <ng-container *ngFor=\"let columna of columnasDe(tablaAmpliada)\" [matColumnDef]=\"columna\">\r\n <th mat-header-cell *matHeaderCellDef>{{ columna }}</th>\r\n <td mat-cell *matCellDef=\"let fila\">{{ fila[columna] }}</td>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\"columnasDe(tablaAmpliada)\"></tr>\r\n <tr mat-row *matRowDef=\"let fila; columns: columnasDe(tablaAmpliada);\"></tr>\r\n </table>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<!-- Aviso ef\u00EDmero tras copiar al portapapeles. -->\r\n<div class=\"chat-ia-copiado-aviso\" *ngIf=\"copiadoAviso\">Tabla copiada</div>\r\n",
981
+ styles: [":host{position:fixed;right:32px;bottom:32px;z-index:1000;font-family:Roboto,sans-serif}.chat-ia-panel{width:450px;height:650px;max-width:calc(100vw - 48px);max-height:calc(100vh - 96px);background:#fff;border-radius:18px;box-shadow:0 24px 60px rgba(20,25,30,.28);display:flex;flex-direction:column;overflow:hidden}.chat-ia-header{background:linear-gradient(135deg,#7c5ce0,#5f42bd);padding:16px 18px;display:flex;align-items:center;justify-content:space-between;flex-shrink:0}.chat-ia-header-info{display:flex;align-items:center;gap:10px;min-width:0}.chat-ia-header-icono{width:32px;height:32px;border-radius:50%;background:rgba(255,255,255,.22);display:flex;align-items:center;justify-content:center;flex:none}.chat-ia-titulo{color:#fff;font-size:14px;font-weight:500}.chat-ia-subtitulo{color:rgba(255,255,255,.75);font-size:11px;margin-top:1px}.chat-ia-cerrar{width:24px;height:24px;display:flex;align-items:center;justify-content:center;cursor:pointer;opacity:.85;flex:none}.chat-ia-cerrar:hover{opacity:1}.chat-ia-mensajes{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:12px;padding:16px;background:#fbfafc}.chat-ia-mensaje{display:flex}.chat-ia-mensaje .chat-ia-burbuja{max-width:88%;background:#f2eefb;color:#26313a;border-radius:14px 14px 14px 3px;padding:10px 13px;font-size:13px;line-height:1.5}.chat-ia-mensaje .chat-ia-burbuja-error{background:#fdecea;color:#7a1f14}.chat-ia-mensaje.chat-ia-mensaje-usuario{justify-content:flex-end}.chat-ia-mensaje.chat-ia-mensaje-usuario .chat-ia-burbuja{background:#7c5ce0;color:#fff;border-radius:14px 14px 3px}.chat-ia-bienvenida-texto{align-self:flex-start;max-width:88%;background:#f2eefb;color:#26313a;border-radius:14px 14px 14px 3px;padding:10px 13px;font-size:13px;line-height:1.5}.chips-chat-ia{flex:none;display:flex;flex-direction:column;align-items:flex-start;gap:6px;padding:0 16px 10px}.chip-chat-ia{max-width:100%;border:1px solid #e7e2f5;background:#f2eefb;color:#5f42bd;border-radius:14px;padding:5px 10px;font-size:11px;line-height:1.35;cursor:pointer;overflow-wrap:anywhere}.chip-chat-ia:hover{background:#e7ddfa}.chip-chat-ia-toggle{flex:none;align-self:flex-start;display:inline-flex;align-items:center;gap:6px;margin:10px 16px;border:1px solid #e7e2f5;background:#f2eefb;color:#5f42bd;border-radius:16px;padding:6px 12px;font-size:12px;cursor:pointer}.chip-chat-ia-toggle .chip-chat-ia-toggle-chevron{transition:transform .15s}.chip-chat-ia-toggle .chip-chat-ia-toggle-chevron.abierto{transform:rotate(180deg)}.chip-chat-ia-toggle:hover{background:#e7ddfa}.chat-ia-descripcion{font-size:13px;line-height:1.5;margin-bottom:6px}.chat-ia-sin-resultados{color:#5a5a5a;font-style:italic}.chat-ia-stat{margin-top:4px}.chat-ia-stat-valor{font-size:30px;font-weight:600;color:#5f42bd;line-height:1.15;font-variant-numeric:proportional-nums}.chat-ia-lista-simple,.chat-ia-tabla-bloque{margin-top:4px;background:#fff;border-radius:10px;padding:8px 10px}.chat-ia-lista-simple{font-size:13px;line-height:1.5}.chat-ia-tabla-acciones{display:flex;justify-content:flex-end;align-items:center;gap:2px;margin-bottom:2px}.chat-ia-accion{width:26px;height:26px;border:none;background:0 0;color:#6b6478;border-radius:7px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;padding:0;flex:none}.chat-ia-accion:hover{background:#f2eefb}.chat-ia-accion .mat-icon{font-size:17px;width:17px;height:17px;line-height:17px}.chat-ia-accion.chat-ia-accion-clara{color:rgba(255,255,255,.9)}.chat-ia-accion.chat-ia-accion-clara:hover{background:rgba(255,255,255,.18);color:#fff}.chat-ia-tabla-resultado{overflow-x:auto;max-width:100%}.chat-ia-tabla-resultado table{font-size:12px;background:0 0}.chat-ia-tabla-resultado th.mat-header-cell{color:#6b6478;font-weight:600;padding:0 14px 5px 0;border-bottom:1px solid #f0edf7;white-space:nowrap}.chat-ia-tabla-resultado td.mat-cell{padding:7px 14px 0 0;white-space:nowrap;font-variant-numeric:tabular-nums}.chat-ia-pensando{align-self:flex-start;background:#f2eefb;padding:12px 16px;border-radius:14px 14px 14px 3px;display:flex;gap:5px;flex-shrink:0}.chat-ia-dot{width:6px;height:6px;border-radius:50%;background:#9a93ae;-webkit-animation:1.1s ease-in-out infinite chatIaBlink;animation:1.1s ease-in-out infinite chatIaBlink}.chat-ia-dot:nth-child(2){-webkit-animation-delay:.15s;animation-delay:.15s}.chat-ia-dot:nth-child(3){-webkit-animation-delay:.3s;animation-delay:.3s}@-webkit-keyframes chatIaBlink{0%,100%,80%{opacity:.25}40%{opacity:1}}@keyframes chatIaBlink{0%,100%,80%{opacity:.25}40%{opacity:1}}.chat-ia-entrada{padding:10px 14px 14px;border-top:1px solid #e9f2ee;flex-shrink:0}.chat-ia-caja-entrada{position:relative;background:#f2f7f5;border:1px solid #e6efea;border-radius:18px;padding:10px 12px 8px}.chat-ia-caja-entrada textarea{border:none;outline:0;background:0 0;width:100%;font:inherit;font-size:13.5px;color:#26313a;resize:none;line-height:1.45;max-height:110px;overflow-y:auto;display:block;padding:0 28px 0 0}.chat-ia-caja-entrada textarea.chat-ia-textarea-expandido{max-height:160px}.chat-ia-caja-entrada textarea::-webkit-input-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea::-moz-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea:-ms-input-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea::-ms-input-placeholder{color:#9a93ae}.chat-ia-caja-entrada textarea::placeholder{color:#9a93ae}.chat-ia-expandir{position:absolute;top:8px;right:10px;font-size:17px;height:17px;width:17px;color:#9a9a9a;cursor:pointer}.chat-ia-pie-entrada{display:flex;align-items:center;justify-content:flex-end;gap:8px;margin-top:8px}.chat-ia-selector-modelo{display:inline-flex;align-items:center;gap:4px;border:none;background:0 0;color:#4e5d57;border-radius:14px;padding:5px 9px;font-size:11.5px;font-weight:600;cursor:pointer}.chat-ia-enviar{width:32px;height:32px;border-radius:50%;border:none;background:#7c5ce0;color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none}.chat-ia-enviar:disabled{background:#dce6e1;color:#a9bab3;cursor:default}.chat-ia-microfono{width:28px;height:28px;border-radius:50%;border:none;background:0 0;color:#6b6478;display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none}.chat-ia-microfono:hover{background:#f2eefb}.chat-ia-microfono.chat-ia-microfono-activo{color:#fff;background:#e05a5a;-webkit-animation:1.1s ease-in-out infinite chatIaBlink;animation:1.1s ease-in-out infinite chatIaBlink}::ng-deep .mat-menu-panel.menu-modelo-chat-ia{min-width:132px;border:1px solid #e6efea;border-radius:10px;box-shadow:0 12px 26px rgba(20,25,30,.16)}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-content{padding:4px}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-item{display:flex;align-items:center;justify-content:space-between;gap:8px;height:auto;line-height:normal;padding:7px 10px;font-size:12px;color:#26313a;border-radius:7px}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-item.opcion-activa{background:#f2f7f5}::ng-deep .mat-menu-panel.menu-modelo-chat-ia .mat-menu-item .chat-ia-check{color:#7c5ce0}.chat-ia-modal-overlay{position:fixed;inset:0;background:rgba(20,25,30,.5);display:flex;align-items:center;justify-content:center;padding:24px;z-index:1100}.chat-ia-modal{background:#fff;border-radius:16px;box-shadow:0 24px 60px rgba(20,25,30,.32);width:auto;max-width:92vw;max-height:86vh;display:flex;flex-direction:column;overflow:hidden}.chat-ia-modal-header{background:linear-gradient(135deg,#7c5ce0,#5f42bd);padding:12px 16px;display:flex;align-items:center;justify-content:space-between;gap:16px;flex-shrink:0}.chat-ia-modal-titulo{color:#fff;font-size:14px;font-weight:500;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chat-ia-modal-acciones{display:flex;align-items:center;gap:2px;flex:none}.chat-ia-modal-tabla{flex:1;min-height:0;overflow:auto;padding:10px 16px 16px}.chat-ia-modal-tabla table{font-size:13px;background:0 0;width:100%}.chat-ia-modal-tabla th.mat-header-cell{color:#6b6478;font-weight:600;padding:0 18px 8px 0;border-bottom:1px solid #f0edf7;white-space:nowrap}.chat-ia-modal-tabla td.mat-cell{padding:9px 18px 9px 0;white-space:nowrap;color:#26313a;border-bottom:1px solid #f6f4fb;font-variant-numeric:tabular-nums}.chat-ia-copiado-aviso{position:fixed;top:24px;left:50%;transform:translateX(-50%);background:#26313a;color:#fff;font-size:12.5px;padding:8px 16px;border-radius:20px;box-shadow:0 8px 20px rgba(20,25,30,.25);z-index:1200;-webkit-animation:.15s ease-out chatIaAvisoEntrada;animation:.15s ease-out chatIaAvisoEntrada}@-webkit-keyframes chatIaAvisoEntrada{from{opacity:0;transform:translate(-50%,-6px)}to{opacity:1;transform:translate(-50%,0)}}@keyframes chatIaAvisoEntrada{from{opacity:0;transform:translate(-50%,-6px)}to{opacity:1;transform:translate(-50%,0)}}::ng-deep .mat-menu-panel.menu-export-chat-ia{min-width:132px;border:1px solid #e6efea;border-radius:10px;box-shadow:0 12px 26px rgba(20,25,30,.16)}::ng-deep .mat-menu-panel.menu-export-chat-ia .mat-menu-content{padding:4px}::ng-deep .mat-menu-panel.menu-export-chat-ia .mat-menu-item{height:auto;line-height:normal;padding:8px 12px;font-size:12px;color:#26313a;border-radius:7px}::ng-deep .mat-menu-panel.menu-export-chat-ia .mat-menu-item:hover{background:#f2f7f5}"]
965
982
  })
966
983
  ], AsistenteDatosComponent);
967
984
  return AsistenteDatosComponent;