iatoolkit 0.3.9__py3-none-any.whl → 0.107.4__py3-none-any.whl

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.

Files changed (150) hide show
  1. iatoolkit/__init__.py +27 -35
  2. iatoolkit/base_company.py +3 -35
  3. iatoolkit/cli_commands.py +18 -47
  4. iatoolkit/common/__init__.py +0 -0
  5. iatoolkit/common/exceptions.py +48 -0
  6. iatoolkit/common/interfaces/__init__.py +0 -0
  7. iatoolkit/common/interfaces/asset_storage.py +34 -0
  8. iatoolkit/common/interfaces/database_provider.py +39 -0
  9. iatoolkit/common/model_registry.py +159 -0
  10. iatoolkit/common/routes.py +138 -0
  11. iatoolkit/common/session_manager.py +26 -0
  12. iatoolkit/common/util.py +353 -0
  13. iatoolkit/company_registry.py +66 -29
  14. iatoolkit/core.py +514 -0
  15. iatoolkit/infra/__init__.py +5 -0
  16. iatoolkit/infra/brevo_mail_app.py +123 -0
  17. iatoolkit/infra/call_service.py +140 -0
  18. iatoolkit/infra/connectors/__init__.py +5 -0
  19. iatoolkit/infra/connectors/file_connector.py +17 -0
  20. iatoolkit/infra/connectors/file_connector_factory.py +57 -0
  21. iatoolkit/infra/connectors/google_cloud_storage_connector.py +53 -0
  22. iatoolkit/infra/connectors/google_drive_connector.py +68 -0
  23. iatoolkit/infra/connectors/local_file_connector.py +46 -0
  24. iatoolkit/infra/connectors/s3_connector.py +33 -0
  25. iatoolkit/infra/google_chat_app.py +57 -0
  26. iatoolkit/infra/llm_providers/__init__.py +0 -0
  27. iatoolkit/infra/llm_providers/deepseek_adapter.py +278 -0
  28. iatoolkit/infra/llm_providers/gemini_adapter.py +350 -0
  29. iatoolkit/infra/llm_providers/openai_adapter.py +124 -0
  30. iatoolkit/infra/llm_proxy.py +268 -0
  31. iatoolkit/infra/llm_response.py +45 -0
  32. iatoolkit/infra/redis_session_manager.py +122 -0
  33. iatoolkit/locales/en.yaml +222 -0
  34. iatoolkit/locales/es.yaml +225 -0
  35. iatoolkit/repositories/__init__.py +5 -0
  36. iatoolkit/repositories/database_manager.py +187 -0
  37. iatoolkit/repositories/document_repo.py +33 -0
  38. iatoolkit/repositories/filesystem_asset_repository.py +36 -0
  39. iatoolkit/repositories/llm_query_repo.py +105 -0
  40. iatoolkit/repositories/models.py +279 -0
  41. iatoolkit/repositories/profile_repo.py +171 -0
  42. iatoolkit/repositories/vs_repo.py +150 -0
  43. iatoolkit/services/__init__.py +5 -0
  44. iatoolkit/services/auth_service.py +193 -0
  45. {services → iatoolkit/services}/benchmark_service.py +7 -7
  46. iatoolkit/services/branding_service.py +153 -0
  47. iatoolkit/services/company_context_service.py +214 -0
  48. iatoolkit/services/configuration_service.py +375 -0
  49. iatoolkit/services/dispatcher_service.py +134 -0
  50. {services → iatoolkit/services}/document_service.py +20 -8
  51. iatoolkit/services/embedding_service.py +148 -0
  52. iatoolkit/services/excel_service.py +156 -0
  53. {services → iatoolkit/services}/file_processor_service.py +36 -21
  54. iatoolkit/services/history_manager_service.py +208 -0
  55. iatoolkit/services/i18n_service.py +104 -0
  56. iatoolkit/services/jwt_service.py +80 -0
  57. iatoolkit/services/language_service.py +89 -0
  58. iatoolkit/services/license_service.py +82 -0
  59. iatoolkit/services/llm_client_service.py +438 -0
  60. iatoolkit/services/load_documents_service.py +174 -0
  61. iatoolkit/services/mail_service.py +213 -0
  62. {services → iatoolkit/services}/profile_service.py +200 -101
  63. iatoolkit/services/prompt_service.py +303 -0
  64. iatoolkit/services/query_service.py +467 -0
  65. iatoolkit/services/search_service.py +55 -0
  66. iatoolkit/services/sql_service.py +169 -0
  67. iatoolkit/services/tool_service.py +246 -0
  68. iatoolkit/services/user_feedback_service.py +117 -0
  69. iatoolkit/services/user_session_context_service.py +213 -0
  70. iatoolkit/static/images/fernando.jpeg +0 -0
  71. iatoolkit/static/images/iatoolkit_core.png +0 -0
  72. iatoolkit/static/images/iatoolkit_logo.png +0 -0
  73. iatoolkit/static/js/chat_feedback_button.js +80 -0
  74. iatoolkit/static/js/chat_filepond.js +85 -0
  75. iatoolkit/static/js/chat_help_content.js +124 -0
  76. iatoolkit/static/js/chat_history_button.js +110 -0
  77. iatoolkit/static/js/chat_logout_button.js +36 -0
  78. iatoolkit/static/js/chat_main.js +401 -0
  79. iatoolkit/static/js/chat_model_selector.js +227 -0
  80. iatoolkit/static/js/chat_onboarding_button.js +103 -0
  81. iatoolkit/static/js/chat_prompt_manager.js +94 -0
  82. iatoolkit/static/js/chat_reload_button.js +38 -0
  83. iatoolkit/static/styles/chat_iatoolkit.css +559 -0
  84. iatoolkit/static/styles/chat_modal.css +133 -0
  85. iatoolkit/static/styles/chat_public.css +135 -0
  86. iatoolkit/static/styles/documents.css +598 -0
  87. iatoolkit/static/styles/landing_page.css +398 -0
  88. iatoolkit/static/styles/llm_output.css +148 -0
  89. iatoolkit/static/styles/onboarding.css +176 -0
  90. iatoolkit/system_prompts/__init__.py +0 -0
  91. iatoolkit/system_prompts/query_main.prompt +30 -23
  92. iatoolkit/system_prompts/sql_rules.prompt +47 -12
  93. iatoolkit/templates/_company_header.html +45 -0
  94. iatoolkit/templates/_login_widget.html +42 -0
  95. iatoolkit/templates/base.html +78 -0
  96. iatoolkit/templates/change_password.html +66 -0
  97. iatoolkit/templates/chat.html +337 -0
  98. iatoolkit/templates/chat_modals.html +185 -0
  99. iatoolkit/templates/error.html +51 -0
  100. iatoolkit/templates/forgot_password.html +51 -0
  101. iatoolkit/templates/onboarding_shell.html +106 -0
  102. iatoolkit/templates/signup.html +79 -0
  103. iatoolkit/views/__init__.py +5 -0
  104. iatoolkit/views/base_login_view.py +96 -0
  105. iatoolkit/views/change_password_view.py +116 -0
  106. iatoolkit/views/chat_view.py +76 -0
  107. iatoolkit/views/embedding_api_view.py +65 -0
  108. iatoolkit/views/forgot_password_view.py +75 -0
  109. iatoolkit/views/help_content_api_view.py +54 -0
  110. iatoolkit/views/history_api_view.py +56 -0
  111. iatoolkit/views/home_view.py +63 -0
  112. iatoolkit/views/init_context_api_view.py +74 -0
  113. iatoolkit/views/llmquery_api_view.py +59 -0
  114. iatoolkit/views/load_company_configuration_api_view.py +49 -0
  115. iatoolkit/views/load_document_api_view.py +65 -0
  116. iatoolkit/views/login_view.py +170 -0
  117. iatoolkit/views/logout_api_view.py +57 -0
  118. iatoolkit/views/profile_api_view.py +46 -0
  119. iatoolkit/views/prompt_api_view.py +37 -0
  120. iatoolkit/views/root_redirect_view.py +22 -0
  121. iatoolkit/views/signup_view.py +100 -0
  122. iatoolkit/views/static_page_view.py +27 -0
  123. iatoolkit/views/user_feedback_api_view.py +60 -0
  124. iatoolkit/views/users_api_view.py +33 -0
  125. iatoolkit/views/verify_user_view.py +60 -0
  126. iatoolkit-0.107.4.dist-info/METADATA +268 -0
  127. iatoolkit-0.107.4.dist-info/RECORD +132 -0
  128. iatoolkit-0.107.4.dist-info/licenses/LICENSE +21 -0
  129. iatoolkit-0.107.4.dist-info/licenses/LICENSE_COMMUNITY.md +15 -0
  130. {iatoolkit-0.3.9.dist-info → iatoolkit-0.107.4.dist-info}/top_level.txt +0 -1
  131. iatoolkit/iatoolkit.py +0 -413
  132. iatoolkit/system_prompts/arquitectura.prompt +0 -32
  133. iatoolkit-0.3.9.dist-info/METADATA +0 -252
  134. iatoolkit-0.3.9.dist-info/RECORD +0 -32
  135. services/__init__.py +0 -5
  136. services/api_service.py +0 -75
  137. services/dispatcher_service.py +0 -351
  138. services/excel_service.py +0 -98
  139. services/history_service.py +0 -45
  140. services/jwt_service.py +0 -91
  141. services/load_documents_service.py +0 -212
  142. services/mail_service.py +0 -62
  143. services/prompt_manager_service.py +0 -172
  144. services/query_service.py +0 -334
  145. services/search_service.py +0 -32
  146. services/sql_service.py +0 -42
  147. services/tasks_service.py +0 -188
  148. services/user_feedback_service.py +0 -67
  149. services/user_session_context_service.py +0 -85
  150. {iatoolkit-0.3.9.dist-info → iatoolkit-0.107.4.dist-info}/WHEEL +0 -0
@@ -0,0 +1,337 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}{{ branding.name }} IA{% endblock %}
4
+
5
+ {% block content %}
6
+ <div class="chat-layout-container container">
7
+ {% block styles %}
8
+ {# Movemos los estilos y los links aquí para que se rendericen en el <head> #}
9
+ <style>
10
+ {{ branding.css_variables | safe }}
11
+ </style>
12
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
13
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
14
+
15
+ {% endblock %}
16
+
17
+ <!-- Sección de encabezado con el usuario conectado -->
18
+ <div id="company-section"
19
+ class="company-section d-flex flex-column flex-md-row justify-content-md-between align-items-center px-3 py-2"
20
+ style="{{ branding.header_style }}">
21
+
22
+ <!-- Fila 1 (Móvil) / Columna Izquierda (Desktop): Nombre de la Empresa -->
23
+ <div class="d-flex align-items-center mb-2 mb-md-0">
24
+ <span style="{{ branding.primary_text_style }}">
25
+ {{ branding.name }}
26
+ </span>
27
+ <span class="ms-2" data-bs-toggle="tooltip" data-bs-placement="bottom"
28
+ title="Powered by IAToolkit {{ license }} ver. {{ iatoolkit_version }}">
29
+ <i class="bi bi-info-circle" style="color: {{ branding.header_text_color }}; opacity: 0.7; font-size: 0.9rem;"></i>
30
+ </span>
31
+
32
+ </div>
33
+
34
+ <!-- Contenedor para la derecha que agrupa ID de usuario y botones -->
35
+ <div class="d-flex flex-column flex-md-row align-items-center">
36
+
37
+ <!-- Fila 2 (Móvil) / Parte 1 de la Columna Derecha (Desktop): ID de Usuario -->
38
+ <span style="{{ branding.secondary_text_style }}" class="mb-2 mb-md-0">
39
+ {{ user_identifier }}
40
+ </span>
41
+
42
+
43
+ <!-- Separador Vertical (Solo visible en Desktop) -->
44
+ <div class="vr mx-3 d-none d-md-block"></div>
45
+
46
+ <!-- Fila 3 (Móvil) / Parte 2 de la Columna Derecha (Desktop): Iconos de Acción -->
47
+ <div class="d-flex align-items-center">
48
+ <!-- Selector de modelo LLM -->
49
+ <button type="button"
50
+ id="llm-model-button"
51
+ class="btn btn-sm py-1 px-3"
52
+ style="border-radius: 0.4rem; border: 1px solid rgba(255,255,255,0.7); background: rgba(0,0,0,0.08); color: {{ branding.header_text_color }};">
53
+ <i class="bi bi-cpu me-1"></i>
54
+ <span id="llm-model-button-label">
55
+ {{ (llm_available_models[0].label if llm_available_models and llm_available_models[0].label else llm_default_model) or 'Modelo IA' }}
56
+ </span>
57
+ </button>
58
+ <!-- Popup simple para selección de modelo -->
59
+ <div id="llm-model-popup"
60
+ class="card shadow-sm llm-model-popup"
61
+ style="position: absolute; z-index: 9999; display: none; min-width: 260px;">
62
+ <div class="card-body py-2">
63
+ <div class="small mb-1 fw-bold">Modelo de IA</div>
64
+ <div class="small mb-2 llm-model-subtitle">
65
+ Este modelo se usará en las próximas consultas.
66
+ </div>
67
+ <div id="llm-model-list" class="list-group list-group-flush">
68
+ {# El contenido se inyecta vía JavaScript con window.availableLlmModels #}
69
+ </div>
70
+ </div>
71
+ </div>
72
+ <a href="javascript:void(0);"
73
+ id="history-button"
74
+ class="ms-3 action-icon-style" title="{{ t('ui.tooltips.history') }}"
75
+ style="color: {{ branding.header_text_color }};">
76
+ <i class="bi bi-clock-history"></i>
77
+ </a>
78
+ <a href="javascript:void(0);"
79
+ id="force-reload-button"
80
+ class="ms-3 action-icon-style"
81
+ title="{{ t('ui.tooltips.reload_context') }}"
82
+ style="color: {{ branding.header_text_color }};">
83
+ <i class="bi bi-arrow-clockwise"></i>
84
+ </a>
85
+ <a href="javascript:void(0);"
86
+ id="send-feedback-button"
87
+ class="ms-3 action-icon-style"
88
+ title="{{ t('ui.tooltips.feedback') }}"
89
+ style="color: {{ branding.header_text_color }};">
90
+ <i class="bi bi-emoji-smile"></i>
91
+ </a>
92
+
93
+ <a href="javascript:void(0);"
94
+ id="onboarding-button"
95
+ class="ms-3 action-icon-style"
96
+ title="{{ t('ui.tooltips.onboarding') }}"
97
+ style="color: {{ branding.header_text_color }};">
98
+ <i class="bi bi-lightbulb"></i>
99
+ </a>
100
+ <a href="javascript:void(0);"
101
+ id="open-help-button"
102
+ class="ms-3 action-icon-style"
103
+ title="{{ t('ui.tooltips.usage_guide') }}"
104
+ style="color: {{ branding.header_text_color }};">
105
+ <i class="bi bi-question-circle-fill"></i>
106
+ </a>
107
+ {% if user_role == "admin" and license == 'enterprise' %}
108
+ <a href="/{{ company_short_name }}/admin"
109
+ target="_blank"
110
+ id="preferences-button"
111
+ class="ms-3 action-icon-style"
112
+ title="{{ t('ui.tooltips.preferences') }}"
113
+ style="color: {{ branding.header_text_color }};">
114
+ <i class="bi bi-gear"></i>
115
+ </a>
116
+ {% endif %}
117
+ <a href="javascript:void(0);"
118
+ id="logout-button"
119
+ class="ms-3 action-icon-style"
120
+ title="{{ t('ui.tooltips.logout') }}"
121
+ style="color: {{ branding.header_text_color }}; !important;">
122
+ <i class="bi bi-box-arrow-right"></i>
123
+ </a>
124
+ </div>
125
+ </div>
126
+ </div>
127
+
128
+ <div id="chat-container"
129
+ class="chat-block mt-2 flex-grow-1" style="overflow-y: auto;">
130
+
131
+ <!-- Mensaje de bienvenida -->
132
+ <div class="answer-section">
133
+ {{ t('ui.chat.welcome_message') }}
134
+ </div>
135
+ </div>
136
+
137
+ <!-- Input oculto de FilePond -->
138
+ <div class="filepond-container" style="display: none;">
139
+ <input type="file" id="file-upload" class="filepond" data-max-files="5" multiple>
140
+ </div>
141
+
142
+ <div id="input-area" class="input-area chat-block mt-2 mb-2">
143
+
144
+ <!-- 1. Contenido Colapsable del Asistente de prompts -->
145
+ <div class="collapse" id="prompt-assistant-collapse">
146
+ <div class="card card-body mb-2">
147
+ <div class="row g-2">
148
+ {% set prompt_col_class = 'col-md-4' %}
149
+ <div class="{{ prompt_col_class }}">
150
+ <div class="position-relative h-100">
151
+ <div class="input-group dropup h-100">
152
+ <button type="button" id="prompt-select-button"
153
+ class="btn prompt-select-button border dropdown-toggle w-100 text-start"
154
+ data-bs-toggle="dropdown"
155
+ aria-expanded="false">
156
+ {{ t('ui.chat.prompts_available') }} ....
157
+ </button>
158
+ <ul class="dropdown-menu dropdown-menu-soft w-100">
159
+ {% if prompts and prompts.message %}
160
+ {% for category_group in prompts.message %}
161
+ <li><h6 class="dropdown-header">{{ category_group.category_name }}</h6></li>
162
+ {% for prompt in category_group.prompts %}
163
+ <li>
164
+ <a class="dropdown-item" href="#"
165
+ data-prompt-name="{{ prompt.prompt }}"
166
+ data-prompt-description="{{ prompt.description }}"
167
+ data-custom-fields='{{ prompt.custom_fields | tojson }}'>
168
+ {{ prompt.description }}
169
+ </a>
170
+ </li>
171
+ {% endfor %}
172
+ {% if not loop.last %}
173
+ <li><hr class="dropdown-divider"></li>
174
+ {% endif %}
175
+ {% endfor %}
176
+ {% endif %}
177
+ </ul>
178
+ </div>
179
+ <button type="button"
180
+ id="clear-selection-button"
181
+ class="btn clear-specific-data-button position-absolute end-0 me-1" style="display: none;">
182
+ <i class="bi bi-x-circle-fill"></i>
183
+ </button>
184
+ </div>
185
+ <input type="hidden" id="prompt-select-value" name="prompt_select_value">
186
+ <input type="hidden" id="prompt-select-description" name="prompt-select-description">
187
+ </div>
188
+ <!-- Contenedor donde JavaScript inyectará los inputs dinámicos -->
189
+ <div id="dynamic-inputs-container" class="col-md">
190
+ <!-- aca se renderizarán los customs_fields del prompt seleccionado -->
191
+ </div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+
196
+ <!-- 2. La Barra de Entrada Principal -->
197
+ <div id="chat-input-bar" class="chat-input-bar d-flex align-items-center">
198
+ <!-- Iconos de la izquierda -->
199
+ <div class="d-flex align-items-center">
200
+ <!-- varita magica -->
201
+ <a class="p-2" href="#prompt-assistant-collapse" data-bs-toggle="collapse" role="button"
202
+ aria-expanded="false" aria-controls="prompt-assistant-collapse"
203
+ title="{{ t('ui.tooltips.use_prompt_assistant') }}">
204
+ <i class="bi bi-magic"></i>
205
+ </a>
206
+ <a class="p-2" href="javascript:void(0);" id="paperclip-button"
207
+ title="{{ t('ui.tooltips.attach_files') }}">
208
+ <i class="bi bi-plus-circle"></i>
209
+ </a>
210
+ <div id="view-files-button-container" style="display: none;">
211
+ <a class="p-2" href="javascript:void(0);" id="view-files-button"
212
+ title="{{ t('ui.tooltips.view_attached_files') }}">
213
+ <i class="bi bi-file-earmark-text"></i>
214
+ </a>
215
+ </div>
216
+ </div>
217
+
218
+ <!-- Textarea Central -->
219
+ <textarea id="question" placeholder="{{ t('ui.chat.input_placeholder') }}"
220
+ class="form-control chat-textarea" style="resize: none;" rows="1"></textarea>
221
+
222
+ <!-- Botón de Enviar a la derecha -->
223
+ <div class="d-flex align-items-center">
224
+ <div id="send-button-container">
225
+ <a href="javascript:void(0);" id="send-button"
226
+ class="p-2 send-button-icon"
227
+ title="{{ t('ui.buttons.send') }}">
228
+ <i class="bi bi-arrow-up-circle-fill"></i>
229
+ </a>
230
+ </div>
231
+ <div id="stop-button-container" style="display: none;">
232
+ <a href="javascript:void(0);" id="stop-button"
233
+ class="p-2 text-danger"
234
+ title="{{ t('ui.buttons.stop') }}">
235
+ <i class="bi bi-stop-circle-fill"></i>
236
+ </a>
237
+ </div>
238
+ </div>
239
+ </div>
240
+ </div>
241
+
242
+ <!-- Incluir los modales desde un archivo externo -->
243
+ {% include 'chat_modals.html' %}
244
+
245
+ </div>
246
+ {% endblock %}
247
+
248
+ {% block scripts %}
249
+ <script>
250
+ // --- Global Configuration from Backend ---
251
+ window.companyShortName = "{{ company_short_name }}";
252
+ window.user_identifier = "{{ user_identifier }}";
253
+ window.redeemToken = {{ redeem_token | tojson | default('null') }};
254
+ window.iatoolkit_base_url = "{{ iatoolkit_base_url }}";
255
+ window.availablePrompts = {{ prompts.message | tojson }};
256
+ window.onboardingCards = {{ onboarding_cards | tojson }};
257
+ window.sendButtonColor = "{{ branding.send_button_color }}";
258
+
259
+ // LLM configuration from backend
260
+ window.defaultLlmModel = {{ llm_default_model | tojson }};
261
+ window.availableLlmModels = {{ llm_available_models | tojson }};
262
+
263
+
264
+ // JS translations helper
265
+ window.i18n = {{ js_translations | tojson }};
266
+ function t_js(key) {
267
+ return window.i18n[key] || key;
268
+ }
269
+
270
+
271
+ </script>
272
+
273
+ <!-- Carga de los scripts JS externos después de definir las variables globales -->
274
+ <script src="{{ url_for('static', filename='js/chat_history_button.js', _external=True) }}"></script>
275
+ <script src="{{ url_for('static', filename='js/chat_reload_button.js', _external=True) }}"></script>
276
+ <script src="{{ url_for('static', filename='js/chat_feedback_button.js', _external=True) }}"></script>
277
+ <script src="{{ url_for('static', filename='js/chat_help_content.js', _external=True) }}"></script>
278
+ <script src="{{ url_for('static', filename='js/chat_onboarding_button.js', _external=True) }}"></script>
279
+ <script src="{{ url_for('static', filename='js/chat_logout_button.js', _external=True) }}"></script>
280
+ <script src="{{ url_for('static', filename='js/chat_prompt_manager.js', _external=True) }}"></script>
281
+ <script src="{{ url_for('static', filename='js/chat_filepond.js', _external=True) }}"></script>
282
+ <script src="{{ url_for('static', filename='js/chat_model_selector.js', _external=True) }}"></script>
283
+ <script src="{{ url_for('static', filename='js/chat_main.js', _external=True) }}"></script>
284
+
285
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
286
+
287
+ <script>
288
+
289
+ document.addEventListener('DOMContentLoaded', function () {
290
+ // Inicializar todos los tooltips de la página
291
+ var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
292
+ var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
293
+ return new bootstrap.Tooltip(tooltipTriggerEl)
294
+ })
295
+ });
296
+
297
+ // Inicialización del modal de onboarding
298
+ document.addEventListener('DOMContentLoaded', function () {
299
+ const btn = document.getElementById('onboarding-button');
300
+ if (!btn) return;
301
+
302
+ const modalEl = document.getElementById('onboardingModal');
303
+ const modal = new bootstrap.Modal(modalEl);
304
+
305
+ if (!window.initOnboarding) {
306
+ console.error('initOnboarding no disponible. Verifica chat_onboarding.js');
307
+ return;
308
+ }
309
+
310
+ const onboarding = initOnboarding({
311
+ mode: 'modal',
312
+ cards: Array.isArray(window.onboardingCards) ? window.onboardingCards : [],
313
+ ui: {
314
+ icon: '#ob-icon',
315
+ title: '#ob-title',
316
+ text: '#ob-text',
317
+ example: '#ob-example',
318
+ dots: '#ob-dots',
319
+ prev: '#ob-prev',
320
+ next: '#ob-next'
321
+ },
322
+ autoRotateMs: 5000
323
+ });
324
+
325
+ modalEl.addEventListener('hidden.bs.modal', () => onboarding.stop());
326
+
327
+ btn.addEventListener('click', () => {
328
+ if (!onboarding.hasCards()) {
329
+ toastr.info('No hay información de onboarding disponible.');
330
+ return;
331
+ }
332
+ onboarding.start();
333
+ modal.show();
334
+ });
335
+ });
336
+ </script>
337
+ {% endblock %}
@@ -0,0 +1,185 @@
1
+
2
+
3
+ <!-- Modal para historial -->
4
+ <div class="modal fade" id="historyModal" tabindex="-1" aria-labelledby="historyModalLabel" aria-hidden="true">
5
+ <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
6
+ <div class="modal-content">
7
+ <div class="modal-header branded">
8
+ <h5 class="modal-title" id="historyModalLabel">
9
+ <i class="bi bi-clock-history me-3"></i>
10
+ {{ t('ui.modals.history_title') }}
11
+ </h5>
12
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
13
+ </div>
14
+ <div class="modal-body">
15
+ <div id="history-loading" style="display: none;" class="text-center p-4">
16
+ <div class="spinner-border text-primary" role="status">
17
+ <span class="visually-hidden">Cargando...</span>
18
+ </div>
19
+ <p class="mt-2">{{ t('ui.modals.loading_history') }}</p>
20
+ </div>
21
+
22
+ <div id="history-content" style="display: none;">
23
+ <div class="table-responsive">
24
+ <table class="table table-striped table-hover">
25
+ <thead class="thead-branded">
26
+ <tr>
27
+ <th scope="col">{{ t('ui.modals.history_table_date') }}</th>
28
+ <th scope="col">{{ t('ui.modals.history_table_query') }}</th>
29
+ <th scope="col" class="col-icon"></th>
30
+ </tr>
31
+ </thead>
32
+ <tbody id="history-table-body">
33
+ <!-- Los datos se cargarán aquí -->
34
+ </tbody>
35
+ </table>
36
+ </div>
37
+ <div id="no-history-message" style="display: none;">
38
+ {{ t('js_messages.no_history_found') }}
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <div class="modal-footer">
43
+ <button type="button" class="btn btn-branded-secondary" data-bs-dismiss="modal">
44
+ <i class="bi bi-x-circle me-1"></i>
45
+ {{ t('ui.buttons.cancel') }}
46
+ </button>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+
52
+
53
+ <!-- Modal para feedback -->
54
+ <div class="modal fade" id="feedbackModal" tabindex="-1" aria-labelledby="feedbackModalLabel" aria-hidden="true">
55
+ <div class="modal-dialog modal-dialog-centered">
56
+ <div class="modal-content">
57
+ <div class="modal-header branded">
58
+ <h5 class="modal-title" id="feedbackModalLabel">
59
+ <i class="bi bi-chat-dots me-3"></i>
60
+ {{ t('ui.modals.feedback_title') }}
61
+ </h5>
62
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
63
+ </div>
64
+ <div class="modal-body">
65
+ <p class="text-center mb-2"><strong>{{ t('ui.modals.feedback_prompt') }}</strong></p>
66
+
67
+ <div class="rating-stars mb-4">
68
+ <span class="star" data-rating="1" onclick="gfg(1)"></span>
69
+ <span class="star" data-rating="2" onclick="gfg(2)"></span>
70
+ <span class="star" data-rating="3" onclick="gfg(3)"></span>
71
+ <span class="star" data-rating="4" onclick="gfg(4)"></span>
72
+ <span class="star" data-rating="5" onclick="gfg(5)"></span>
73
+ </div>
74
+
75
+ <div class="form-group">
76
+ <label for="feedback-text" class="form-label text-muted">
77
+ {{ t('ui.modals.feedback_comment_label') }}</label>
78
+ <textarea
79
+ class="form-control feedback-text"
80
+ id="feedback-text"
81
+ rows="4"
82
+ placeholder="{{ t('ui.modals.feedback_comment_placeholder') }}"
83
+ style="resize: vertical; min-height: 100px;"></textarea>
84
+ </div>
85
+ </div>
86
+ <div class="modal-footer">
87
+ <button type="button" class="btn btn-branded-secondary" data-bs-dismiss="modal">
88
+ <i class="bi bi-x-circle me-1"></i>
89
+ {{ t('ui.buttons.cancel') }}
90
+ </button>
91
+ <button type="button" class="btn btn-branded-primary" id="submit-feedback">
92
+ <i class="bi bi-send me-1"></i>
93
+ {{ t('ui.buttons.send') }}
94
+ </button>
95
+ </div>
96
+ </div>
97
+ </div>
98
+ </div>
99
+
100
+
101
+ <!-- Modal de Onboarding -->
102
+ <div class="modal fade" id="onboardingModal" tabindex="-1" aria-labelledby="onboardingModalLabel" aria-hidden="true">
103
+ <div class="modal-dialog modal-dialog-centered">
104
+ <div class="modal-content" style="border-radius:12px;">
105
+ <div class="modal-header">
106
+ <h5 class="modal-title w-100 text-center" id="onboardingModalLabel" style="color: var(--brand-primary-color, #FF5100);">
107
+ {{ branding.name }}
108
+ </h5>
109
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
110
+ </div>
111
+
112
+ <div class="modal-body ob-root">
113
+ <div id="ob-card" class="ob-card">
114
+ <div id="ob-icon" class="ob-icon"><i class="bi bi-lightbulb"></i></div>
115
+ <h6 id="ob-title" class="ob-title"></h6>
116
+ <div id="ob-text" class="ob-text"></div>
117
+ <div id="ob-example" class="ob-example"></div>
118
+ <div class="ob-nav">
119
+ <button id="ob-prev" class="ob-btn" aria-label="Anterior"><i class="bi bi-chevron-left"></i></button>
120
+ <div id="ob-dots" class="ob-dots"></div>
121
+ <button id="ob-next" class="ob-btn" aria-label="Siguiente"><i class="bi bi-chevron-right"></i></button>
122
+ </div>
123
+ </div>
124
+ </div>
125
+
126
+ <div class="modal-footer">
127
+ <button id="ob-close" type="button" class="btn btn-branded-primary" data-bs-dismiss="modal">
128
+ {{ t('ui.buttons.cancel') }}
129
+ </button>
130
+ </div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+
135
+ <!-- Modal de Guía de Uso / Ayuda -->
136
+ <div class="modal fade" id="helpModal" tabindex="-1" aria-labelledby="helpModalLabel" aria-hidden="true">
137
+ <div class="modal-dialog modal-lg modal-dialog-scrollable">
138
+ <div class="modal-content">
139
+ <div class="modal-header branded">
140
+ <h5 class="modal-title" id="helpModalLabel">
141
+ <i class="bi bi-info-circle me-2"></i>
142
+ {{ t('ui.modals.help_title') }}
143
+ </h5>
144
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
145
+ </div>
146
+ <div class="modal-body">
147
+ <!-- El acordeón con el contenido de ayuda se inyectará aquí dinámicamente -->
148
+ <div id="help-spinner" class="text-center p-5" style="display: none;">
149
+ <div class="spinner-border text-primary" role="status">
150
+ <span class="visually-hidden">Cargando...</span>
151
+ </div>
152
+ </div>
153
+ <div class="accordion" id="help-accordion-container">
154
+ <!-- Contenido generado por JS -->
155
+ </div>
156
+ </div>
157
+ <div class="modal-footer">
158
+ <button type="button" class="btn btn-branded-secondary"
159
+ data-bs-dismiss="modal">
160
+ {{ t('ui.buttons.cancel') }}
161
+ </button>
162
+ </div>
163
+ </div>
164
+ </div>
165
+ </div>
166
+
167
+ <!-- Modal para mostrar archivos cargados -->
168
+ <div class="modal fade" id="uploadedFilesModal" tabindex="-1" aria-labelledby="uploadedFilesModalLabel" aria-hidden="true">
169
+ <div class="modal-dialog">
170
+ <div class="modal-content">
171
+ <div class="modal-header branded">
172
+ <h5 class="modal-title" id="uploadedFilesModalLabel">Archivos Cargados</h5>
173
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
174
+ </div>
175
+ <div class="modal-body">
176
+ <ul id="uploaded-files-list" class="list-group">
177
+ <!-- Los nombres de los archivos se agregarán aquí por JS -->
178
+ </ul>
179
+ </div>
180
+ <div class="modal-footer">
181
+ <button type="button" class="btn btn-branded-secondary" data-bs-dismiss="modal">Cerrar</button>
182
+ </div>
183
+ </div>
184
+ </div>
185
+ </div>
@@ -0,0 +1,51 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Error{% endblock %}
4
+
5
+ {% block styles %}
6
+ {# Carga las variables de CSS personalizadas de la empresa #}
7
+ {% if branding %}
8
+ <style>
9
+ {{ branding.css_variables | safe }}
10
+ </style>
11
+ {% endif %}
12
+ {# Enlace a los iconos de Bootstrap para el icono de error #}
13
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
14
+ {% endblock %}
15
+
16
+ {% block content %}
17
+ <div class="container mt-4">
18
+
19
+ {% include '_company_header.html' %}
20
+
21
+ {# Contenedor principal para el mensaje de error #}
22
+ <div class="container mt-5">
23
+ <div class="row justify-content-center">
24
+ <div class="col-md-8 col-lg-6">
25
+
26
+ {# Usamos una tarjeta para enmarcar el contenido del error #}
27
+ <div class="card shadow-sm text-center border-danger">
28
+ <div class="card-body p-4 p-md-5">
29
+
30
+ {# Icono de error grande y visible #}
31
+ <i class="bi bi-exclamation-triangle-fill text-danger" style="font-size: 4rem;"></i>
32
+
33
+ <h4 class="card-title mt-4">Ha Ocurrido un Error</h4>
34
+ <h5 class="card-title mt-4">Empresa: {{ company_short_name }} </h5>
35
+
36
+ {# El mensaje de error dinámico que se pasa desde la vista #}
37
+ <p class="text-muted mt-3 mb-4">
38
+ {{ message | default('Lo sentimos, algo salió mal. Por favor, inténtalo de nuevo más tarde.') }}
39
+ </p>
40
+
41
+ <a href="javascript:history.back()"
42
+ class="btn btn-branded-primary px-4">
43
+ Volver
44
+ </a>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ {% endblock %}
@@ -0,0 +1,51 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}{{ t('ui.forgot_password.title') }} - {{ branding.name }}{% endblock %}
4
+
5
+ {% block styles %}
6
+ <style>{{ branding.css_variables | safe }}</style>
7
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_public.css') }}">
8
+ {% endblock %}
9
+
10
+ {% block content %}
11
+ <div class="container mt-4">
12
+
13
+ {% include '_company_header.html' %}
14
+
15
+ <!-- 3. Sección contenedora para centrar el contenido -->
16
+ <section class="hero-section">
17
+ <div class="container">
18
+ <div class="row justify-content-center">
19
+ <div class="col-lg-6 col-md-8">
20
+ <div class="branded-form-container">
21
+ <h4 class="branded-form-title">{{ t('ui.forgot_password.title') }}</h4>
22
+
23
+ <p class="text-muted text-center mb-4">
24
+ {{ t('ui.forgot_password.subtitle') }}
25
+ </p>
26
+
27
+ <form action="{{ url_for('forgot_password', company_short_name=company_short_name, lang=lang) }}" method="post">
28
+ <input type="hidden" name="lang" value="{{ lang }}">
29
+ <div class="mb-3">
30
+ <label for="email" class="form-label text-secondary">{{ t('ui.signup.email_label') }}</label>
31
+ <input type="email" id="email" name="email"
32
+ class="form-control"
33
+ required value="{{ form_data.email if form_data else '' }}">
34
+ </div>
35
+
36
+ <button type="submit" class="btn btn-branded-primary w-100 fw-bold py-2 mt-3">{{ t('ui.forgot_password.submit_button') }}</button>
37
+ </form>
38
+
39
+ <div class="text-center mt-4 pt-3" style="border-top: 1px solid #e0e0e0;">
40
+ <a href="{{ url_for('home', company_short_name=company_short_name, lang=request.args.get('lang', 'en')) }}" class="text-muted text-decoration-none fw-semibold">
41
+ <i class="bi bi-arrow-left me-1"></i>{{ t('ui.forgot_password.back_to_login') }}
42
+ </a>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </section>
49
+ </div>
50
+
51
+ {% endblock %}