iatoolkit 0.10.2__tar.gz → 0.11.1__tar.gz
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.
Potentially problematic release.
This version of iatoolkit might be problematic. Click here for more details.
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/PKG-INFO +1 -1
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/pyproject.toml +1 -1
- iatoolkit-0.11.1/src/iatoolkit/services/branding_service.py +109 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/history_service.py +1 -1
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/js/chat_history.js +2 -1
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/js/chat_main.js +77 -52
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/styles/chat_iatoolkit.css +66 -11
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/styles/chat_modal.css +50 -39
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/chat.html +21 -16
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/chat_modals.html +9 -9
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit.egg-info/PKG-INFO +1 -1
- iatoolkit-0.10.2/src/iatoolkit/services/branding_service.py +0 -71
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/readme.md +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/requirements.txt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/setup.cfg +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/common/auth.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/common/routes.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/iatoolkit.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/gemini_adapter.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/llm_client.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/mail_app.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/openai_adapter.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/models.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/tasks_repo.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/benchmark_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/document_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/load_documents_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/prompt_manager_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/query_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/search_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/tasks_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/arrow_up.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/logo_clinica.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/logo_iatoolkit.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/logo_maxxa.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/logo_notaria.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/logo_tarjeta.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/logo_umayor.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/images/upload.png +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/js/chat_feedback.js +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/styles/chat_info.css +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/about.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/header.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/home.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/login.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/templates/test.html +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/chat_token_request_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/download_file_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/external_chat_login_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/external_login_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/file_store_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/history_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/llmquery_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/prompt_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/tasks_review_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/tasks_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/user_feedback_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-0.10.2 → iatoolkit-0.11.1}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
from iatoolkit.repositories.models import Company
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BrandingService:
|
|
10
|
+
"""
|
|
11
|
+
Servicio centralizado que gestiona la configuración de branding.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self):
|
|
15
|
+
"""
|
|
16
|
+
Define los estilos de branding por defecto para la aplicación.
|
|
17
|
+
"""
|
|
18
|
+
self._default_branding = {
|
|
19
|
+
# --- Estilos del Encabezado Principal ---
|
|
20
|
+
"header_background_color": "#FFFFFF",
|
|
21
|
+
"header_text_color": "#6C757D",
|
|
22
|
+
"primary_font_weight": "bold",
|
|
23
|
+
"primary_font_size": "1rem",
|
|
24
|
+
"secondary_font_weight": "600",
|
|
25
|
+
"secondary_font_size": "0.875rem",
|
|
26
|
+
"tertiary_font_weight": "normal",
|
|
27
|
+
"tertiary_font_size": "0.75rem",
|
|
28
|
+
"tertiary_opacity": "0.8",
|
|
29
|
+
|
|
30
|
+
# Estilos Globales de la Marca ---
|
|
31
|
+
"brand_primary_color": "#0d6efd", # Azul de Bootstrap por defecto
|
|
32
|
+
"brand_secondary_color": "#6c757d", # Gris de Bootstrap por defecto
|
|
33
|
+
"brand_text_on_primary": "#FFFFFF", # Texto blanco sobre color primario
|
|
34
|
+
"brand_text_on_secondary": "#FFFFFF", # Texto blanco sobre color secundario
|
|
35
|
+
|
|
36
|
+
# Estilos para Alertas de Error ---
|
|
37
|
+
"brand_danger_color": "#dc3545", # Rojo principal para alertas
|
|
38
|
+
"brand_danger_bg": "#f8d7da", # Fondo rojo pálido
|
|
39
|
+
"brand_danger_text": "#842029", # Texto rojo oscuro
|
|
40
|
+
"brand_danger_border": "#f5c2c7", # Borde rojo intermedio
|
|
41
|
+
|
|
42
|
+
# Estilos para Alertas Informativas ---
|
|
43
|
+
"brand_info_bg": "#cff4fc", # Fondo celeste pálido
|
|
44
|
+
"brand_info_text": "#055160", # Texto azul oscuro
|
|
45
|
+
"brand_info_border": "#b6effb",
|
|
46
|
+
|
|
47
|
+
# Color para el botón de Enviar ---
|
|
48
|
+
"send_button_color": "#212529" # Gris oscuro/casi negro por defecto
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
def get_company_branding(self, company: Company | None) -> dict:
|
|
52
|
+
"""
|
|
53
|
+
Retorna los estilos de branding finales para una compañía,
|
|
54
|
+
fusionando los valores por defecto con los personalizados.
|
|
55
|
+
"""
|
|
56
|
+
final_branding_values = self._default_branding.copy()
|
|
57
|
+
|
|
58
|
+
if company and company.branding:
|
|
59
|
+
final_branding_values.update(company.branding)
|
|
60
|
+
|
|
61
|
+
# --- CONSTRUCCIÓN DE ESTILOS Y VARIABLES CSS ---
|
|
62
|
+
header_style = (
|
|
63
|
+
f"background-color: {final_branding_values['header_background_color']}; "
|
|
64
|
+
f"color: {final_branding_values['header_text_color']};"
|
|
65
|
+
)
|
|
66
|
+
primary_text_style = (
|
|
67
|
+
f"font-weight: {final_branding_values['primary_font_weight']}; "
|
|
68
|
+
f"font-size: {final_branding_values['primary_font_size']};"
|
|
69
|
+
)
|
|
70
|
+
secondary_text_style = (
|
|
71
|
+
f"font-weight: {final_branding_values['secondary_font_weight']}; "
|
|
72
|
+
f"font-size: {final_branding_values['secondary_font_size']};"
|
|
73
|
+
)
|
|
74
|
+
tertiary_text_style = (
|
|
75
|
+
f"font-weight: {final_branding_values['tertiary_font_weight']}; "
|
|
76
|
+
f"font-size: {final_branding_values['tertiary_font_size']}; "
|
|
77
|
+
f"opacity: {final_branding_values['tertiary_opacity']};"
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Generamos el bloque de variables CSS
|
|
81
|
+
css_variables = f"""
|
|
82
|
+
:root {{
|
|
83
|
+
--brand-primary-color: {final_branding_values['brand_primary_color']};
|
|
84
|
+
--brand-secondary-color: {final_branding_values['brand_secondary_color']};
|
|
85
|
+
--brand-text-on-primary: {final_branding_values['brand_text_on_primary']};
|
|
86
|
+
--brand-text-on-secondary: {final_branding_values['brand_text_on_secondary']};
|
|
87
|
+
--brand-modal-header-bg: {final_branding_values['header_background_color']};
|
|
88
|
+
--brand-modal-header-text: {final_branding_values['header_text_color']};
|
|
89
|
+
--brand-danger-color: {final_branding_values['brand_danger_color']};
|
|
90
|
+
--brand-danger-bg: {final_branding_values['brand_danger_bg']};
|
|
91
|
+
--brand-danger-text: {final_branding_values['brand_danger_text']};
|
|
92
|
+
--brand-danger-border: {final_branding_values['brand_danger_border']};
|
|
93
|
+
--brand-info-bg: {final_branding_values['brand_info_bg']};
|
|
94
|
+
--brand-info-text: {final_branding_values['brand_info_text']};
|
|
95
|
+
--brand-info-border: {final_branding_values['brand_info_border']};
|
|
96
|
+
|
|
97
|
+
}}
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
"name": company.name if company else "IAToolkit",
|
|
102
|
+
"header_style": header_style,
|
|
103
|
+
"primary_text_style": primary_text_style,
|
|
104
|
+
"secondary_text_style": secondary_text_style,
|
|
105
|
+
"tertiary_text_style": tertiary_text_style,
|
|
106
|
+
"header_text_color": final_branding_values['header_text_color'],
|
|
107
|
+
"css_variables": css_variables,
|
|
108
|
+
"send_button_color": final_branding_values['send_button_color']
|
|
109
|
+
}
|
|
@@ -36,7 +36,7 @@ class HistoryService:
|
|
|
36
36
|
history = self.llm_query_repo.get_history(company, user_identifier)
|
|
37
37
|
|
|
38
38
|
if not history:
|
|
39
|
-
return {'
|
|
39
|
+
return {'message': 'Historial vacio actualmente', 'history': []}
|
|
40
40
|
|
|
41
41
|
history_list = [query.to_dict() for query in history]
|
|
42
42
|
|
|
@@ -41,7 +41,7 @@ $(document).ready(function () {
|
|
|
41
41
|
} catch (error) {
|
|
42
42
|
console.error("Error al cargar historial:", error);
|
|
43
43
|
const errorHtml = `
|
|
44
|
-
<div class="alert alert-danger alert-dismissible show" role="alert">
|
|
44
|
+
<div class="alert alert-branded-danger alert-dismissible show" role="alert">
|
|
45
45
|
<strong>Error al cargar el historial:</strong> ${error.message}
|
|
46
46
|
<button type="button" class="close" data-dismiss="alert">
|
|
47
47
|
<span>×</span>
|
|
@@ -92,6 +92,7 @@ $(document).ready(function () {
|
|
|
92
92
|
|
|
93
93
|
// Copiar el texto al textarea del chat
|
|
94
94
|
$('#question').val(queryText);
|
|
95
|
+
$('#send-button').removeClass('disabled');
|
|
95
96
|
|
|
96
97
|
// Cerrar el modal
|
|
97
98
|
$('#historyModal').modal('hide');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Global variables for request management
|
|
2
|
-
let currentAbortController = null;
|
|
3
2
|
let isRequestInProgress = false;
|
|
3
|
+
let abortController = null;
|
|
4
4
|
|
|
5
5
|
let selectedPrompt = null; // Will hold a lightweight prompt object
|
|
6
6
|
|
|
@@ -8,6 +8,8 @@ $(document).ready(function () {
|
|
|
8
8
|
// --- MAIN EVENT HANDLERS ---
|
|
9
9
|
$('#send-button').on('click', handleChatMessage);
|
|
10
10
|
$('#stop-button').on('click', abortCurrentRequest);
|
|
11
|
+
if (window.sendButtonColor)
|
|
12
|
+
$('#send-button i').css('color', window.sendButtonColor);
|
|
11
13
|
|
|
12
14
|
// --- PROMPT ASSISTANT FUNCTIONALITY ---
|
|
13
15
|
$('.input-area').on('click', '.dropdown-menu a.dropdown-item', function (event) {
|
|
@@ -118,75 +120,99 @@ function renderDynamicInputs(fields) {
|
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
|
|
123
|
+
|
|
121
124
|
/**
|
|
122
125
|
* Main function to handle sending a chat message.
|
|
123
126
|
*/
|
|
124
127
|
const handleChatMessage = async function () {
|
|
125
|
-
if (isRequestInProgress || $('#send-button').hasClass('disabled'))
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const promptName = selectedPrompt ? selectedPrompt.prompt : null;
|
|
128
|
+
if (isRequestInProgress || $('#send-button').hasClass('disabled')) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
129
131
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const clientData = {};
|
|
132
|
+
isRequestInProgress = true;
|
|
133
|
+
toggleSendStopButtons(true);
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
try {
|
|
136
|
+
const question = $('#question').val().trim();
|
|
137
|
+
const promptName = selectedPrompt ? selectedPrompt.prompt : null;
|
|
137
138
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
clientData[field.data_key] = value;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
139
|
+
let displayMessage = question;
|
|
140
|
+
let isEditable = true;
|
|
141
|
+
const clientData = {};
|
|
144
142
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
if (selectedPrompt) {
|
|
144
|
+
displayMessage = selectedPrompt.description;
|
|
145
|
+
isEditable = false;
|
|
146
|
+
|
|
147
|
+
(selectedPrompt.custom_fields || []).forEach(field => {
|
|
148
|
+
const value = $('#' + field.data_key + '-id').val().trim();
|
|
149
|
+
if (value) {
|
|
150
|
+
clientData[field.data_key] = value;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const paramsString = Object.values(clientData).join(', ');
|
|
155
|
+
if (paramsString) { displayMessage += `: ${paramsString}`; }
|
|
149
156
|
}
|
|
150
|
-
}
|
|
151
157
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
toggleSendStopButtons(true);
|
|
158
|
+
// Simplificado: Si no hay mensaje, el 'finally' se encargará de limpiar.
|
|
159
|
+
// Simplemente salimos de la función.
|
|
160
|
+
if (!displayMessage) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
158
163
|
|
|
159
|
-
|
|
164
|
+
displayUserMessage(displayMessage, isEditable, question);
|
|
165
|
+
showSpinner();
|
|
166
|
+
resetAllInputs();
|
|
160
167
|
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
const files = window.filePond.getFiles();
|
|
169
|
+
const filesBase64 = await Promise.all(files.map(fileItem => toBase64(fileItem.file)));
|
|
163
170
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
};
|
|
171
|
+
const data = {
|
|
172
|
+
question: question,
|
|
173
|
+
prompt_name: promptName,
|
|
174
|
+
client_data: clientData,
|
|
175
|
+
files: filesBase64.map(f => ({ filename: f.name, content: f.base64 })),
|
|
176
|
+
external_user_id: window.externalUserId
|
|
177
|
+
};
|
|
172
178
|
|
|
173
|
-
try {
|
|
174
179
|
const responseData = await callLLMAPI("/llm_query", data, "POST");
|
|
175
180
|
if (responseData && responseData.answer) {
|
|
176
181
|
const answerSection = $('<div>').addClass('answer-section llm-output').append(responseData.answer);
|
|
177
182
|
displayBotMessage(answerSection);
|
|
178
183
|
}
|
|
179
184
|
} catch (error) {
|
|
180
|
-
|
|
181
|
-
|
|
185
|
+
if (error.name === 'AbortError') {
|
|
186
|
+
console.log('Petición abortada por el usuario.');
|
|
187
|
+
|
|
188
|
+
// Usando jQuery estándar para construir el elemento ---
|
|
189
|
+
const icon = $('<i>').addClass('bi bi-stop-circle me-2'); // Icono sin "fill" para un look más ligero
|
|
190
|
+
const textSpan = $('<span>').text('La generación de la respuesta ha sido detenida.');
|
|
191
|
+
|
|
192
|
+
const abortMessage = $('<div>')
|
|
193
|
+
.addClass('system-message')
|
|
194
|
+
.append(icon)
|
|
195
|
+
.append(textSpan);
|
|
196
|
+
|
|
197
|
+
displayBotMessage(abortMessage);
|
|
198
|
+
} else {
|
|
199
|
+
console.error("Error in handleChatMessage:", error);
|
|
200
|
+
const errorSection = $('<div>').addClass('error-section').append('<p>Ocurrió un error al procesar la solicitud.</p>');
|
|
201
|
+
displayBotMessage(errorSection);
|
|
202
|
+
}
|
|
182
203
|
} finally {
|
|
204
|
+
// Este bloque se ejecuta siempre, garantizando que el estado se limpie.
|
|
205
|
+
isRequestInProgress = false;
|
|
183
206
|
hideSpinner();
|
|
184
207
|
toggleSendStopButtons(false);
|
|
185
208
|
updateSendButtonState();
|
|
186
|
-
window.filePond
|
|
209
|
+
if (window.filePond) {
|
|
210
|
+
window.filePond.removeFiles();
|
|
211
|
+
}
|
|
187
212
|
}
|
|
188
213
|
};
|
|
189
214
|
|
|
215
|
+
|
|
190
216
|
/**
|
|
191
217
|
* Resets all inputs to their initial state.
|
|
192
218
|
*/
|
|
@@ -274,16 +300,15 @@ const callLLMAPI = async function(apiPath, data, method, timeoutMs = 500000) {
|
|
|
274
300
|
headers['X-Chat-Token'] = window.sessionJWT;
|
|
275
301
|
}
|
|
276
302
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
303
|
+
abortController = new AbortController();
|
|
304
|
+
const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
|
|
280
305
|
|
|
281
306
|
try {
|
|
282
307
|
const response = await fetch(url, {
|
|
283
308
|
method: method,
|
|
284
309
|
headers: headers,
|
|
285
310
|
body: JSON.stringify(data),
|
|
286
|
-
signal:
|
|
311
|
+
signal: abortController.signal, // Se usa el signal del controlador global
|
|
287
312
|
credentials: 'include'
|
|
288
313
|
});
|
|
289
314
|
clearTimeout(timeoutId);
|
|
@@ -322,10 +347,11 @@ const displayUserMessage = function(message, isEditable, originalQuestion) {
|
|
|
322
347
|
userMessage.append(messageText);
|
|
323
348
|
|
|
324
349
|
if (isEditable) {
|
|
325
|
-
const editIcon = $('<i>').addClass('bi bi-pencil-fill edit-icon').attr('title', 'Edit query').on('click', function () {
|
|
350
|
+
const editIcon = $('<i>').addClass('p-2 bi bi-pencil-fill edit-icon').attr('title', 'Edit query').on('click', function () {
|
|
326
351
|
$('#question').val(originalQuestion).focus();
|
|
327
352
|
autoResizeTextarea($('#question')[0]);
|
|
328
|
-
|
|
353
|
+
|
|
354
|
+
$('#send-button').removeClass('disabled');
|
|
329
355
|
});
|
|
330
356
|
userMessage.append(editIcon);
|
|
331
357
|
}
|
|
@@ -347,9 +373,8 @@ function displayBotMessage(section) {
|
|
|
347
373
|
* Aborts the current in-progress API request.
|
|
348
374
|
*/
|
|
349
375
|
const abortCurrentRequest = function () {
|
|
350
|
-
if (
|
|
351
|
-
|
|
352
|
-
currentAbortController.abort();
|
|
376
|
+
if (isRequestInProgress && abortController) {
|
|
377
|
+
abortController.abort();
|
|
353
378
|
}
|
|
354
379
|
};
|
|
355
380
|
|
|
@@ -1,3 +1,34 @@
|
|
|
1
|
+
/* Customización de variables de Bootstrap */
|
|
2
|
+
:root {
|
|
3
|
+
--bs-tooltip-bg: #495057; /* Gris carbón, más claro y profesional */
|
|
4
|
+
--bs-tooltip-opacity: 0.95; /* Ligeramente más opaco para mejor legibilidad */
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.alert-branded-danger {
|
|
8
|
+
background-color: var(--brand-danger-bg);
|
|
9
|
+
color: var(--brand-danger-text);
|
|
10
|
+
border-color: var(--brand-danger-border);
|
|
11
|
+
}
|
|
12
|
+
/* Asegura que el texto fuerte y los enlaces dentro de la alerta también tomen el color correcto */
|
|
13
|
+
.alert-branded-danger strong,
|
|
14
|
+
.alert-branded-danger .alert-link {
|
|
15
|
+
color: inherit;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
/* esta clase defines los atributos de cada bloque */
|
|
20
|
+
.chat-block {
|
|
21
|
+
padding: 1rem; /* Equivalente a p-3 de Bootstrap */
|
|
22
|
+
border: 1px solid #dee2e6; /* Borde estándar y sutil */
|
|
23
|
+
border-radius: 0.375rem; /* Borde redondeado estándar de Bootstrap */
|
|
24
|
+
box-shadow: 0 2px 8px rgba(0,0,0,0.06); /* Sombra suave y unificada */
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Estilo para la sección del encabezado */
|
|
28
|
+
.company-section {
|
|
29
|
+
border-radius: 0.375rem; /* Mismo radio que .chat-block para consistencia */
|
|
30
|
+
}
|
|
31
|
+
|
|
1
32
|
/* Spinner */
|
|
2
33
|
.spinning {
|
|
3
34
|
animation: spin 1s linear infinite;
|
|
@@ -17,7 +48,6 @@
|
|
|
17
48
|
display: flex;
|
|
18
49
|
flex-direction: column;
|
|
19
50
|
background-color: #fff; /* Fondo blanco para el contenedor del chat */
|
|
20
|
-
box-shadow: 0 0 10px rgba(0,0,0,0.1); /* Sombra sutil */
|
|
21
51
|
}
|
|
22
52
|
.answer-section, .error-section, .document-section {
|
|
23
53
|
max-width: 100%;
|
|
@@ -139,9 +169,6 @@
|
|
|
139
169
|
/* 1. La caja principal que envuelve toda el área de entrada */
|
|
140
170
|
.input-area {
|
|
141
171
|
background-color: #f8f9fa;
|
|
142
|
-
padding: 10px;
|
|
143
|
-
border-radius: 10px;
|
|
144
|
-
box-shadow: 0 -2px 5px rgba(0,0,0,0.05);
|
|
145
172
|
}
|
|
146
173
|
|
|
147
174
|
/* 2. La barra "cápsula" que envuelve el texto y los iconos */
|
|
@@ -149,7 +176,7 @@
|
|
|
149
176
|
background-color: #ffffff;
|
|
150
177
|
border: 1px solid #dee2e6;
|
|
151
178
|
border-radius: 1.5rem;
|
|
152
|
-
padding: 0.
|
|
179
|
+
padding: 0.1rem 0.5rem;
|
|
153
180
|
transition: all 0.2s ease-in-out;
|
|
154
181
|
}
|
|
155
182
|
|
|
@@ -159,6 +186,30 @@
|
|
|
159
186
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
|
160
187
|
}
|
|
161
188
|
|
|
189
|
+
/* Estilo para mensajes sutiles del sistema (ej. abortado) */
|
|
190
|
+
.system-message {
|
|
191
|
+
color: var(--brand-secondary-color, #6c757d); /* Usa el color secundario o un gris por defecto */
|
|
192
|
+
font-style: italic;
|
|
193
|
+
font-size: 0.9rem;
|
|
194
|
+
display: flex;
|
|
195
|
+
align-items: center;
|
|
196
|
+
justify-content: start;
|
|
197
|
+
margin: 10px 0;
|
|
198
|
+
padding: 10px;
|
|
199
|
+
opacity: 0.8;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
#prompt-assistant-collapse .card {
|
|
204
|
+
border-radius: 1.5rem; /* Mismo radio que el chat-input-bar */
|
|
205
|
+
border: 1px solid #dee2e6; /* Mismo borde que el chat-input-bar */
|
|
206
|
+
box-shadow: none; /* Eliminamos la sombra por defecto del card */
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#prompt-assistant-collapse.show .card {
|
|
210
|
+
margin-bottom: 12px !important; /* Anula el mb-2 (8px) para añadir un poco más de espacio */
|
|
211
|
+
}
|
|
212
|
+
|
|
162
213
|
/* 4. El textarea "invisible" en el centro */
|
|
163
214
|
.chat-textarea {
|
|
164
215
|
flex-grow: 1;
|
|
@@ -194,13 +245,12 @@
|
|
|
194
245
|
color: #343a40;
|
|
195
246
|
}
|
|
196
247
|
|
|
197
|
-
/* 6. Anulación
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
font-size: 1.7rem !important; /* Ligeramente más grande para mayor énfasis */
|
|
248
|
+
/* 6. Anulación específica para el botón de ENVIAR usando su ID (Máxima Prioridad) */
|
|
249
|
+
#send-button i {
|
|
250
|
+
font-size: 1.7rem; /* Ligeramente más grande */
|
|
201
251
|
}
|
|
202
|
-
|
|
203
|
-
|
|
252
|
+
#send-button:hover i {
|
|
253
|
+
filter: brightness(85%); /* Efecto hover genérico que funciona con cualquier color */
|
|
204
254
|
}
|
|
205
255
|
|
|
206
256
|
/* 7. Estilo para el botón de enviar cuando está deshabilitado */
|
|
@@ -383,3 +433,8 @@
|
|
|
383
433
|
.star.hover-active {
|
|
384
434
|
color: #ffc107;
|
|
385
435
|
}
|
|
436
|
+
|
|
437
|
+
#send-button i {
|
|
438
|
+
color: var(--brand-send-button-color);
|
|
439
|
+
}
|
|
440
|
+
|
|
@@ -2,10 +2,51 @@
|
|
|
2
2
|
/* Estilos generales para modales */
|
|
3
3
|
/* ######################################################### */
|
|
4
4
|
|
|
5
|
-
/*
|
|
6
|
-
.
|
|
7
|
-
|
|
5
|
+
/* Estilos del header del modal con branding */
|
|
6
|
+
.modal-header.branded {
|
|
7
|
+
background-color: var(--brand-modal-header-bg);
|
|
8
|
+
color: var(--brand-modal-header-text);
|
|
9
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
|
10
|
+
}
|
|
11
|
+
.modal-header.branded .btn-close {
|
|
12
|
+
filter: invert(1) grayscale(100%) brightness(200%); /* Hace el botón de cerrar visible en fondos oscuros */
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Estilos para botones con branding */
|
|
16
|
+
.btn-branded-primary {
|
|
17
|
+
background-color: var(--brand-primary-color);
|
|
18
|
+
border-color: var(--brand-primary-color);
|
|
19
|
+
color: var(--brand-text-on-primary);
|
|
20
|
+
}
|
|
21
|
+
.btn-branded-primary:hover {
|
|
22
|
+
filter: brightness(90%);
|
|
23
|
+
color: var(--brand-text-on-primary);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.btn-branded-secondary {
|
|
27
|
+
background-color: var(--brand-secondary-color);
|
|
28
|
+
border-color: var(--brand-secondary-color);
|
|
29
|
+
color: var(--brand-text-on-secondary);
|
|
8
30
|
}
|
|
31
|
+
.btn-branded-secondary:hover {
|
|
32
|
+
filter: brightness(90%);
|
|
33
|
+
color: var(--brand-text-on-secondary);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Estilos para alertas informativas personalizadas */
|
|
37
|
+
.alert-branded-info {
|
|
38
|
+
background-color: var(--brand-info-bg);
|
|
39
|
+
color: var(--brand-info-text);
|
|
40
|
+
border-color: var(--brand-info-border);
|
|
41
|
+
}
|
|
42
|
+
.alert-branded-info strong,
|
|
43
|
+
.alert-branded-info .alert-link {
|
|
44
|
+
color: inherit;
|
|
45
|
+
}
|
|
46
|
+
.alert-branded-info .bi { /* Asegura que los iconos también tomen el color */
|
|
47
|
+
color: inherit;
|
|
48
|
+
}
|
|
49
|
+
|
|
9
50
|
|
|
10
51
|
/* Título del modal */
|
|
11
52
|
.modal-title{
|
|
@@ -13,11 +54,6 @@
|
|
|
13
54
|
font-weight: bold;
|
|
14
55
|
}
|
|
15
56
|
|
|
16
|
-
/* Texto del modal */
|
|
17
|
-
.text-muted{
|
|
18
|
-
font-size:16px;
|
|
19
|
-
text-align: justify;
|
|
20
|
-
}
|
|
21
57
|
|
|
22
58
|
/* Estilos del header del modal*/
|
|
23
59
|
.modal-header {
|
|
@@ -45,20 +81,17 @@
|
|
|
45
81
|
/* Modal de historial */
|
|
46
82
|
/* ######################################################### */
|
|
47
83
|
|
|
48
|
-
/*
|
|
49
|
-
.thead-
|
|
84
|
+
/* Encabezado de tabla con branding */
|
|
85
|
+
.thead-branded th {
|
|
86
|
+
background-color: var(--brand-primary-color);
|
|
87
|
+
color: var(--brand-text-on-primary);
|
|
50
88
|
font-size: 16px;
|
|
51
89
|
font-weight: bold;
|
|
52
90
|
}
|
|
53
91
|
|
|
54
|
-
/* Control de ancho de columnas en la tabla del historial */
|
|
55
|
-
#history-content .table td:nth-child(1) {
|
|
56
|
-
width: 5%; /* Columna del número */
|
|
57
|
-
}
|
|
58
92
|
|
|
59
|
-
#history-content .table td:nth-child(
|
|
60
|
-
|
|
61
|
-
}
|
|
93
|
+
#history-content .table td:nth-child(1) { width: 5%; }
|
|
94
|
+
#history-content .table td:nth-child(2) { width: 23%; }
|
|
62
95
|
|
|
63
96
|
#history-content .table td:nth-child(3) {
|
|
64
97
|
width: auto; /* Columna de la consulta - ocupa el resto */
|
|
@@ -69,28 +102,6 @@
|
|
|
69
102
|
/* ######################################################### */
|
|
70
103
|
|
|
71
104
|
/* Contenedor de calificación del modal de feedback */
|
|
72
|
-
.rating-container {
|
|
73
|
-
text-align: center;
|
|
74
|
-
margin: 10px 0 0 0;
|
|
75
|
-
display: flex;
|
|
76
|
-
flex-direction: column;
|
|
77
|
-
justify-content: center;
|
|
78
|
-
align-items: center;
|
|
79
|
-
gap: 5px;
|
|
80
|
-
width: 100%;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/* Contenedor de estrellas del modal de feedback */
|
|
84
|
-
.rating-stars-container{
|
|
85
|
-
text-align: center;
|
|
86
|
-
margin: 2px 0 0 0;
|
|
87
|
-
display: flex;
|
|
88
|
-
flex-direction: row;
|
|
89
|
-
justify-content: center;
|
|
90
|
-
align-items: center;
|
|
91
|
-
gap: 10px;
|
|
92
|
-
width: 100%;
|
|
93
|
-
}
|
|
94
105
|
|
|
95
106
|
/* Estilos de las estrellas del modal de feedback */
|
|
96
107
|
.star {
|