iatoolkit 0.66.2__py3-none-any.whl → 0.71.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.
Files changed (73) hide show
  1. iatoolkit/__init__.py +2 -6
  2. iatoolkit/base_company.py +3 -31
  3. iatoolkit/cli_commands.py +1 -1
  4. iatoolkit/common/routes.py +5 -1
  5. iatoolkit/common/session_manager.py +2 -0
  6. iatoolkit/company_registry.py +1 -2
  7. iatoolkit/iatoolkit.py +13 -13
  8. iatoolkit/infra/llm_client.py +8 -12
  9. iatoolkit/infra/llm_proxy.py +38 -10
  10. iatoolkit/locales/en.yaml +25 -2
  11. iatoolkit/locales/es.yaml +27 -4
  12. iatoolkit/repositories/database_manager.py +8 -3
  13. iatoolkit/repositories/document_repo.py +1 -1
  14. iatoolkit/repositories/models.py +6 -8
  15. iatoolkit/repositories/profile_repo.py +0 -4
  16. iatoolkit/repositories/vs_repo.py +26 -20
  17. iatoolkit/services/auth_service.py +2 -2
  18. iatoolkit/services/branding_service.py +11 -7
  19. iatoolkit/services/company_context_service.py +155 -0
  20. iatoolkit/services/configuration_service.py +133 -0
  21. iatoolkit/services/dispatcher_service.py +75 -70
  22. iatoolkit/services/document_service.py +5 -2
  23. iatoolkit/services/embedding_service.py +145 -0
  24. iatoolkit/services/excel_service.py +15 -11
  25. iatoolkit/services/file_processor_service.py +4 -12
  26. iatoolkit/services/history_service.py +7 -7
  27. iatoolkit/services/i18n_service.py +4 -4
  28. iatoolkit/services/jwt_service.py +7 -9
  29. iatoolkit/services/language_service.py +29 -23
  30. iatoolkit/services/load_documents_service.py +100 -113
  31. iatoolkit/services/mail_service.py +9 -4
  32. iatoolkit/services/profile_service.py +10 -7
  33. iatoolkit/services/prompt_manager_service.py +20 -16
  34. iatoolkit/services/query_service.py +112 -43
  35. iatoolkit/services/search_service.py +11 -4
  36. iatoolkit/services/sql_service.py +57 -25
  37. iatoolkit/services/user_feedback_service.py +15 -13
  38. iatoolkit/static/js/chat_history_button.js +3 -5
  39. iatoolkit/static/js/chat_main.js +2 -17
  40. iatoolkit/static/js/chat_onboarding_button.js +6 -0
  41. iatoolkit/static/styles/chat_iatoolkit.css +69 -158
  42. iatoolkit/static/styles/chat_modal.css +1 -37
  43. iatoolkit/static/styles/onboarding.css +7 -0
  44. iatoolkit/system_prompts/query_main.prompt +2 -10
  45. iatoolkit/templates/change_password.html +1 -1
  46. iatoolkit/templates/chat.html +12 -4
  47. iatoolkit/templates/chat_modals.html +4 -0
  48. iatoolkit/templates/error.html +1 -1
  49. iatoolkit/templates/login_simulation.html +17 -6
  50. iatoolkit/templates/onboarding_shell.html +4 -1
  51. iatoolkit/views/base_login_view.py +7 -8
  52. iatoolkit/views/change_password_view.py +2 -3
  53. iatoolkit/views/embedding_api_view.py +65 -0
  54. iatoolkit/views/external_login_view.py +1 -1
  55. iatoolkit/views/file_store_api_view.py +1 -1
  56. iatoolkit/views/forgot_password_view.py +2 -4
  57. iatoolkit/views/help_content_api_view.py +9 -9
  58. iatoolkit/views/history_api_view.py +1 -1
  59. iatoolkit/views/home_view.py +2 -2
  60. iatoolkit/views/init_context_api_view.py +18 -17
  61. iatoolkit/views/llmquery_api_view.py +3 -2
  62. iatoolkit/views/login_simulation_view.py +14 -2
  63. iatoolkit/views/login_view.py +9 -9
  64. iatoolkit/views/signup_view.py +2 -4
  65. iatoolkit/views/verify_user_view.py +2 -4
  66. {iatoolkit-0.66.2.dist-info → iatoolkit-0.71.4.dist-info}/METADATA +40 -22
  67. iatoolkit-0.71.4.dist-info/RECORD +122 -0
  68. iatoolkit-0.71.4.dist-info/licenses/LICENSE +21 -0
  69. iatoolkit/services/help_content_service.py +0 -30
  70. iatoolkit/services/onboarding_service.py +0 -43
  71. iatoolkit-0.66.2.dist-info/RECORD +0 -119
  72. {iatoolkit-0.66.2.dist-info → iatoolkit-0.71.4.dist-info}/WHEEL +0 -0
  73. {iatoolkit-0.66.2.dist-info → iatoolkit-0.71.4.dist-info}/top_level.txt +0 -0
@@ -28,6 +28,7 @@
28
28
  const elIcon = qs(root, ui.icon);
29
29
  const elTitle = qs(root, ui.title);
30
30
  const elText = qs(root, ui.text);
31
+ const elExample = qs(root, ui.example);
31
32
  const elDots = qs(root, ui.dots);
32
33
  const elPrev = qs(root, ui.prev);
33
34
  const elNext = qs(root, ui.next);
@@ -43,6 +44,11 @@
43
44
  if (elIcon) elIcon.innerHTML = `<i class="${c.icon || 'bi bi-lightbulb'}"></i>`;
44
45
  if (elTitle) elTitle.textContent = c.title || '';
45
46
  if (elText) elText.innerHTML = c.text || '';
47
+ if (elExample && c.example) {
48
+ elExample.innerHTML = ('Ejemplo: ' + c.example) || '';
49
+ }
50
+ else
51
+ elExample.innerHTML = '';
46
52
  if (elDots) createDots(elDots, cards.length, idx);
47
53
  }
48
54
 
@@ -23,16 +23,33 @@ li {
23
23
  padding-left: 0.25rem; /* Pequeño espacio extra entre la viñeta y el texto */
24
24
  }
25
25
 
26
- /* Estilo para la viñeta (el punto) de cada elemento de la lista */
27
- li::marker {
28
- color: var(--brand-primary-color); /* La viñeta usa el color principal de la marca */
29
- font-size: 1.1em; /* Ligeramente más grande para que sea más visible */
30
- }
31
-
32
26
  .text-muted {
33
27
  color: #64748b;
34
28
  }
35
29
 
30
+ /* Estilos para botones con branding */
31
+ .btn-branded-primary {
32
+ background-color: var(--brand-primary-color);
33
+ border-color: var(--brand-primary-color);
34
+ color: var(--brand-text-on-primary);
35
+ }
36
+ .btn-branded-primary:hover {
37
+ background-color: var(--brand-text-on-primary);
38
+ color: var(--brand-primary-color);
39
+ border-color: var(--brand-primary-color);
40
+ }
41
+
42
+ .btn-branded-secondary {
43
+ background-color: var(--brand-secondary-color);
44
+ border-color: var(--brand-secondary-color);
45
+ color: var(--brand-text-on-secondary);
46
+ }
47
+ .btn-branded-secondary:hover {
48
+ background-color: var(--brand-text-on-secondary);
49
+ color: var(--brand-secondary-color);
50
+ border-color: var(--brand-secondary-color);
51
+ }
52
+
36
53
  .chat-layout-container {
37
54
  display: flex;
38
55
  flex-direction: column;
@@ -42,21 +59,6 @@ li::marker {
42
59
  padding-bottom: 0.2rem;
43
60
  }
44
61
 
45
- /* Esta parte para el prompt-assistant sigue siendo correcta */
46
- main.chat-layout-container.prompt-assistant-open {
47
- height: auto;
48
- overflow: visible;
49
- }
50
-
51
-
52
- /* CSS para el chat principal */
53
- /* esta clase defines los atributos de cada bloque */
54
- .chat-block {
55
- padding: 1rem;
56
- border: 1px solid #dee2e6;
57
- border-radius: 0.375rem; /* Borde redondeado estándar de Bootstrap */
58
- box-shadow: 0 2px 8px rgba(0,0,0,0.06); /* Sombra suave y unificada */
59
- }
60
62
 
61
63
  /* sección del encabezado en el chat principal */
62
64
  .company-section {
@@ -74,9 +76,24 @@ main.chat-layout-container.prompt-assistant-open {
74
76
  background-color: #fff; /* Fondo blanco para el contenedor del chat */
75
77
  }
76
78
 
77
- /* La caja principal que envuelve toda el área de entrada */
78
- .input-area {
79
- background-color: var(--brand-prompt-assistant-bg, #f8f9fa);
79
+ /* CSS para el chat principal */
80
+ /* esta clase defines los atributos de cada bloque */
81
+ .chat-block {
82
+ padding: 1rem;
83
+ border: 1px solid #dee2e6;
84
+ border-radius: 0.375rem; /* Borde redondeado estándar de Bootstrap */
85
+ box-shadow: 0 2px 8px rgba(0,0,0,0.06); /* Sombra suave y unificada */
86
+ }
87
+
88
+ /* El textarea "invisible" en el centro */
89
+ .chat-textarea {
90
+ flex-grow: 1;
91
+ background: transparent !important;
92
+ border: none !important;
93
+ box-shadow: none !important;
94
+ resize: none;
95
+ max-height: 150px;
96
+ min-height: 38px;
80
97
  }
81
98
 
82
99
  /* La barra "cápsula" que envuelve el texto y los iconos */
@@ -93,6 +110,11 @@ main.chat-layout-container.prompt-assistant-open {
93
110
  border-color: #86b7fe;
94
111
  box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
95
112
  }
113
+ /* La caja principal que envuelve toda el área de entrada */
114
+ .input-area {
115
+ background-color: var(--brand-prompt-assistant-bg, #f8f9fa);
116
+ }
117
+
96
118
 
97
119
  #question {
98
120
  width: 100%;
@@ -109,12 +131,6 @@ main.chat-layout-container.prompt-assistant-open {
109
131
  box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25);
110
132
  }
111
133
 
112
- .answer-section, .error-section {
113
- max-width: 100%;
114
- word-wrap: break-word;
115
- margin-bottom: 10px;
116
- }
117
-
118
134
  /* Estilo del mensaje ingresado por el usuario */
119
135
  #chat-container .message {
120
136
  max-width: 75%;
@@ -134,6 +150,13 @@ main.chat-layout-container.prompt-assistant-open {
134
150
  background-color: #f7f7f8;
135
151
  }
136
152
 
153
+ .answer-section, .error-section {
154
+ max-width: 100%;
155
+ word-wrap: break-word;
156
+ margin-bottom: 10px;
157
+ }
158
+
159
+
137
160
  .answer-section {
138
161
  align-self: flex-start;
139
162
  max-width: 75%;
@@ -184,7 +207,6 @@ main.chat-layout-container.prompt-assistant-open {
184
207
  opacity: 0.8;
185
208
  }
186
209
 
187
-
188
210
  /* Spinner */
189
211
  .spinning {
190
212
  animation: spin 1s linear infinite;
@@ -195,7 +217,6 @@ main.chat-layout-container.prompt-assistant-open {
195
217
  color: var(--brand-primary-color);
196
218
  }
197
219
 
198
-
199
220
  @keyframes spin {
200
221
  0% { transform: rotate(0deg); }
201
222
  100% { transform: rotate(360deg); }
@@ -236,108 +257,6 @@ main.chat-layout-container.prompt-assistant-open {
236
257
  }
237
258
 
238
259
 
239
-
240
- /* Estos estilos son para las paginas publicas: home, signup, olvide la clave, etc */
241
-
242
- /* --- Encabezado (top) de company --- */
243
- .custom-company-header {
244
- height: 78px;
245
- margin-bottom: 20px;
246
- padding: 0 1.5rem; /* Padding interno para que el texto no toque los bordes */
247
- border-radius: 0.375rem; /* Bordes redondeados para que coincida con los formularios */
248
-
249
- /* Los estilos de color y sombra se mantienen */
250
- background-color: var(--brand-header-bg);
251
- color: var(--brand-header-text);
252
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); /* Sombra ligeramente más suave */
253
- }
254
-
255
- /* Estilo específico para el nombre de la marca en el encabezado (Letra más grande) */
256
- .custom-company-header .brand-name {
257
- font-size: 1.8rem; /* Tamaño de fuente aumentado */
258
- font-weight: 600;
259
- color: inherit;
260
- text-decoration: none;
261
- transition: opacity 0.2s ease-in-out;
262
- }
263
-
264
- /* Efecto hover para el enlace del nombre de la marca */
265
- .custom-company-header .brand-name:hover {
266
- opacity: 0.85;
267
- }
268
-
269
- /* Estilo para el texto "Powered by" --- */
270
- .custom-company-header .powered-by {
271
- font-size: 0.9rem;
272
- font-weight: 400;
273
- opacity: 0.75; /* Menos prominente que el nombre de la marca */
274
- color: inherit;
275
- }
276
-
277
- /* --- Estilo para el enlace de IAToolkit --- */
278
- .custom-company-header .iatoolkit-link {
279
- color: inherit; /* Hereda el color del texto padre */
280
- text-decoration: none; /* ¡Elimina el subrayado! */
281
- font-weight: 600; /* Un poco más de peso para diferenciarlo */
282
- transition: opacity 0.2s ease-in-out;
283
- }
284
-
285
- .custom-company-header .form-container {
286
- display: flex;
287
- flex-direction: column;
288
- gap: 1rem;
289
- }
290
-
291
- /* titulo en home */
292
- .home-title {
293
- font-size: 3.2rem;
294
- font-weight: 800;
295
- line-height: 1.2;
296
- color: var(--brand-primary-color);
297
- }
298
- .list-example {
299
- display: block; /* Coloca el ejemplo en su propia línea */
300
- font-size: 0.9rem; /* Lo hace ligeramente más pequeño */
301
- color: #6c757d; /* Color gris (muted) para texto secundario */
302
- font-style: italic; /* Cursiva para diferenciarlo */
303
- padding-left: 1.75rem; /* Lo indenta para alinearlo con el texto del tema */
304
- margin-top: 0.25rem; /* Pequeño espacio superior */
305
- }
306
-
307
- .text-brand-primary {
308
- font-weight: 800;
309
- color: var(--brand-primary-color);
310
- }
311
-
312
- /* contenedor de formularios: login, signup, forgot password, etc. */
313
- .branded-form-container {
314
- background-color: #ffffff;
315
- border: 1px solid #dee2e6;
316
- border-top: 4px solid #adb5bd;
317
- border-radius: 0.375rem;
318
- padding: 2rem;
319
- box-shadow: 0 4px 12px rgba(0,0,0,0.08);
320
- }
321
-
322
- .branded-form-label {
323
- font-size: 0.85rem;
324
- font-weight: 600;
325
- color: #495057; /* Un gris oscuro profesional */
326
- text-transform: uppercase;
327
- letter-spacing: 0.05em; /* Un poco de espacio extra entre letras */
328
- margin-bottom: 0.3rem;
329
- display: block;
330
- }
331
-
332
- .branded-form-title {
333
- color: var(--brand-primary-color);
334
- font-size: 1.75rem; /* Un tamaño más prominente */
335
- font-weight: 700; /* Equivalente a fw-bold de Bootstrap */
336
- text-align: center;
337
- margin-bottom: 1.5rem; /* Espacio consistente debajo del título */
338
- }
339
-
340
-
341
260
  /* Aplica el color secundario de la marca al icono de ver archivos */
342
261
  #view-files-button i {
343
262
  color: var(--brand-secondary-color, #6c757d);
@@ -353,16 +272,6 @@ main.chat-layout-container.prompt-assistant-open {
353
272
  margin-bottom: 12px !important; /* Anula el mb-2 (8px) para añadir un poco más de espacio */
354
273
  }
355
274
 
356
- /* 4. El textarea "invisible" en el centro */
357
- .chat-textarea {
358
- flex-grow: 1;
359
- background: transparent !important;
360
- border: none !important;
361
- box-shadow: none !important;
362
- resize: none;
363
- max-height: 150px;
364
- min-height: 38px;
365
- }
366
275
 
367
276
  /* Estilo UNIFICADO para los enlaces de iconos de acción */
368
277
  .action-icon-style {
@@ -394,7 +303,7 @@ main.chat-layout-container.prompt-assistant-open {
394
303
  color: #343a40;
395
304
  }
396
305
 
397
- /* 6. Anulación específica para el botón de ENVIAR usando su ID (Máxima Prioridad) */
306
+ /* Anulación específica para el botón de ENVIAR usando su ID (Máxima Prioridad) */
398
307
  #send-button i {
399
308
  font-size: 1.7rem; /* Ligeramente más grande */
400
309
  }
@@ -474,30 +383,30 @@ main.chat-layout-container.prompt-assistant-open {
474
383
  border-bottom: none;
475
384
  }
476
385
 
386
+ /* estilos para el selector de prompts */
477
387
  .prompt-select-button {
478
- /* Estado por defecto: Estilo "outline" sutil */
479
- background-color: var(--brand-primary-color);
480
- color: var(--brand-text-on-primary);
481
- border: 1px solid var(--brand-primary-color); /* Borde fino con el color primario */
482
-
483
- /* Estilos de botón estándar */
484
- border-radius: 0.25rem;
388
+ color: #202123;
389
+ border: 2px solid var(--brand-primary-color);
390
+ border-radius: 0.25rem; /* Estilos de botón estándar */
485
391
  padding: 0.5rem 1rem;
486
392
  cursor: pointer;
487
393
  text-align: center;
488
- font-weight: 500; /* Un poco más de peso para el texto */
394
+ font-weight: 500;
489
395
 
490
396
  /* Transición suave para el cambio en hover */
491
397
  transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
492
398
  }
493
399
 
494
400
  .prompt-select-button:hover {
495
- /* Estado hover: Se rellena para dar feedback claro */
496
- background-color: transparent;
497
- color: var(--brand-primary-color);
498
- }
401
+ background-color: var(--brand-primary-color);
402
+ color: var(--brand-text-on-primary);
499
403
 
404
+ /* Marca el borde con un glow limpio */
405
+ border-color: var(--brand-primary-color);
406
+ box-shadow: 0 0 0 3px rgba( var(--brand-primary-rgb), 0.25 );
407
+ }
500
408
 
409
+ /* estilo de la x que limpia el prompt seleccionado */
501
410
  #clear-selection-button {
502
411
  position: absolute;
503
412
  top: 50%;
@@ -510,7 +419,9 @@ main.chat-layout-container.prompt-assistant-open {
510
419
  }
511
420
 
512
421
  #clear-selection-button:hover {
513
- color: #212529;
422
+ color: #ffffff;
423
+ background-color: #6c757d;
424
+ border-radius: 0.25rem;
514
425
  }
515
426
 
516
427
  #send-button i {
@@ -39,28 +39,6 @@
39
39
  filter: invert(1) grayscale(100%) brightness(200%); /* Hace el botón de cerrar visible en fondos oscuros */
40
40
  }
41
41
 
42
- /* Estilos para botones con branding */
43
- .btn-branded-primary {
44
- background-color: var(--brand-primary-color);
45
- border-color: var(--brand-primary-color);
46
- color: var(--brand-text-on-primary);
47
- }
48
- .btn-branded-primary:hover {
49
- background-color: var(--brand-text-on-primary);
50
- color: var(--brand-primary-color);
51
- border-color: var(--brand-primary-color);
52
- }
53
-
54
- .btn-branded-secondary {
55
- background-color: var(--brand-secondary-color);
56
- border-color: var(--brand-secondary-color);
57
- color: var(--brand-text-on-secondary);
58
- }
59
- .btn-branded-secondary:hover {
60
- background-color: var(--brand-text-on-secondary);
61
- color: var(--brand-secondary-color);
62
- border-color: var(--brand-secondary-color);
63
- }
64
42
 
65
43
  /* Tabla con el resultado del historial */
66
44
  .thead-branded th {
@@ -109,7 +87,7 @@
109
87
  box-shadow: none;
110
88
  }
111
89
 
112
- /* 2. Estilo para el anillo de foco, aplicado ÚNICAMENTE cuando el botón está CERRADO y tiene foco. */
90
+ /* Estilo para el anillo de foco, aplicado ÚNICAMENTE cuando el botón está CERRADO y tiene foco. */
113
91
  .modal-body .accordion-button.collapsed:focus {
114
92
  background-color: #fff; /* Asegura fondo blanco al hacer foco en un item cerrado */
115
93
  border-color: transparent; /* Evita bordes no deseados */
@@ -153,17 +131,3 @@
153
131
  .remove-file-btn {
154
132
  flex-shrink: 0;
155
133
  }
156
-
157
- /* Estilos para alertas generales del chat */
158
- .alert-branded-info {
159
- background-color: var(--brand-info-bg);
160
- color: var(--brand-info-text);
161
- border-color: var(--brand-info-border);
162
- }
163
- .alert-branded-info strong,
164
- .alert-branded-info .alert-link {
165
- color: inherit;
166
- }
167
- .alert-branded-info .bi { /* Asegura que los iconos también tomen el color */
168
- color: inherit;
169
- }
@@ -36,6 +36,13 @@
36
36
  min-height: 60px;
37
37
  }
38
38
 
39
+ .ob-example {
40
+ font-size: 0.95rem;
41
+ color: #444;
42
+ line-height: 1.5;
43
+ min-height: 60px;
44
+ }
45
+
39
46
  /* Navegación */
40
47
  .ob-nav {
41
48
  display: flex;
@@ -19,19 +19,11 @@ Eres un asistente que responde preguntas o ejecuta tareas según el contexto de
19
19
  Eres un asistente que responde preguntas sobre empresas y sus clientes.
20
20
 
21
21
  **Reglas obligatorias de contexto:**
22
- 1. Cada vez que el usuario consulte por un cliente,
23
- debes memorizarlo y usarlo como cliente de contexto.
24
- 2. Si el usuario hace una pregunta **sin especificar un cliente**,
25
- siempre debes asumir que la pregunta se refiere al **último cliente identificado** en la conversación.
26
- 3. Nunca cambies de cliente de contexto a menos que el usuario especifique uno nuevo.
27
- 4. Si el usuario pregunta por un cliente que no está en tus registros, responde indicando que no tienes información, pero **no borres el contexto anterior**.
28
- 5. No respondas con “no se encontró información del cliente” salvo que nunca se haya identificado ningún cliente antes en la conversación.
29
- 6. No debes incluir explicaciones, comentarios o texto adicional.
22
+ En caso que te hagan preguntas especificas sobre un cliente, debes asumir que la pregunta se
23
+ refiere al **último cliente identificado** en la conversación.
30
24
 
31
25
  **IMPORTANTE:**
32
26
 
33
- No respondas nunca sobre un cliente anterior si ya se identificó uno nuevo, y nunca pierdas el contexto salvo que el usuario lo cambie explícitamente.
34
-
35
27
  ### **Instrucciones**
36
28
  1. Devuelve siempre la respuesta en formato JSON.
37
29
  2. Usa la información de contexto para responder la consulta del usuario de forma clara y concisa.
@@ -1,6 +1,6 @@
1
1
  {% extends "base.html" %}
2
2
 
3
- {% block title %}{{ t('ui.change_password.title') }} - {{ company.name }}{% endblock %}
3
+ {% block title %}{{ t('ui.change_password.title') }} - {{ branding.name }} {% endblock %}
4
4
 
5
5
  {% block styles %}
6
6
  <style>
@@ -90,8 +90,8 @@
90
90
  </div>
91
91
 
92
92
  <div id="chat-container"
93
- class="chat-block mt-2 flex-grow-1"
94
- style="overflow-y: auto;">
93
+ class="chat-block mt-2 flex-grow-1" style="overflow-y: auto;">
94
+
95
95
  <!-- Mensaje de bienvenida -->
96
96
  <div class="answer-section">
97
97
  {{ t('ui.chat.welcome_message') }}
@@ -113,7 +113,10 @@
113
113
  <div class="{{ prompt_col_class }}">
114
114
  <div class="position-relative h-100">
115
115
  <div class="input-group dropup h-100">
116
- <button type="button" id="prompt-select-button" class="btn prompt-select-button border dropdown-toggle w-100 text-start" data-bs-toggle="dropdown" aria-expanded="false">
116
+ <button type="button" id="prompt-select-button"
117
+ class="btn prompt-select-button border dropdown-toggle w-100 text-start"
118
+ data-bs-toggle="dropdown"
119
+ aria-expanded="false">
117
120
  {{ t('ui.chat.prompts_available') }} ....
118
121
  </button>
119
122
  <ul class="dropdown-menu dropdown-menu-soft w-100">
@@ -137,7 +140,11 @@
137
140
  {% endif %}
138
141
  </ul>
139
142
  </div>
140
- <button type="button" id="clear-selection-button" class="btn clear-specific-data-button" style="display: none;"><i class="bi bi-x-circle-fill"></i></button>
143
+ <button type="button"
144
+ id="clear-selection-button"
145
+ class="btn clear-specific-data-button position-absolute end-0 me-1" style="display: none;">
146
+ <i class="bi bi-x-circle-fill"></i>
147
+ </button>
141
148
  </div>
142
149
  <input type="hidden" id="prompt-select-value" name="prompt_select_value">
143
150
  <input type="hidden" id="prompt-select-description" name="prompt-select-description">
@@ -265,6 +272,7 @@ document.addEventListener('DOMContentLoaded', function () {
265
272
  icon: '#ob-icon',
266
273
  title: '#ob-title',
267
274
  text: '#ob-text',
275
+ example: '#ob-example',
268
276
  dots: '#ob-dots',
269
277
  prev: '#ob-prev',
270
278
  next: '#ob-next'
@@ -34,6 +34,9 @@
34
34
  </tbody>
35
35
  </table>
36
36
  </div>
37
+ <div id="no-history-message" style="display: none;">
38
+ {{ t('js_messages.no_history_found') }}
39
+ </div>
37
40
  </div>
38
41
  </div>
39
42
  <div class="modal-footer">
@@ -111,6 +114,7 @@
111
114
  <div id="ob-icon" class="ob-icon"><i class="bi bi-lightbulb"></i></div>
112
115
  <h6 id="ob-title" class="ob-title"></h6>
113
116
  <div id="ob-text" class="ob-text"></div>
117
+ <div id="ob-example" class="ob-example"></div>
114
118
  <div class="ob-nav">
115
119
  <button id="ob-prev" class="ob-btn" aria-label="Anterior"><i class="bi bi-chevron-left"></i></button>
116
120
  <div id="ob-dots" class="ob-dots"></div>
@@ -1,6 +1,6 @@
1
1
  {% extends "base.html" %}
2
2
 
3
- {% block title %}Error {% endblock %}
3
+ {% block title %}Error{% endblock %}
4
4
 
5
5
  {% block styles %}
6
6
  {# Carga las variables de CSS personalizadas de la empresa #}
@@ -1,15 +1,25 @@
1
1
  {% extends "base.html" %}
2
2
 
3
- {% block title %}Prueba de Login para {{ company_short_name }}{% endblock %}
3
+ {% block title %}Login Test - {{ branding.name }}{% endblock %}
4
+ {% block styles %}
5
+ <style>
6
+ {{ branding.css_variables | safe }}
7
+ </style>
8
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_public.css') }}">
9
+ {% endblock %}
4
10
 
5
11
  {% block content %}
12
+ <div class="container mt-4">
13
+
14
+ {% include '_company_header.html' %}
15
+
6
16
  <div class="container-fluid">
7
17
  <div class="row flex-fill mt-5 justify-content-center">
8
18
  <div class="col-12 col-lg-6">
9
- <div class="border rounded p-4 p-md-5 shadow-sm bg-light">
10
- <h3 class="text-muted fw-semibold text-start mb-3">
11
- Login Externo para <span style="color:#0d6efd;">{{ company_short_name }}</span>
12
- </h3>
19
+ <div class="branded-form-container">
20
+ <h4 class="branded-form-title">
21
+ Login Externo para {{ company_short_name }}
22
+ </h4>
13
23
  <div class="text-center mb-4">
14
24
  <p class="text-muted widget-intro-text">
15
25
  Este formulario simula el inicio de una sesión externa. Al enviar, serás redirigido a la URL de login final.
@@ -22,7 +32,7 @@
22
32
  <label for="external_user_id" class="form-label d-block">External user ID</label>
23
33
  <input type="text" id="external_user_id" name="external_user_id" class="form-control" required>
24
34
  </div>
25
- <button type="submit" class="btn btn-primary">
35
+ <button type="submit" class="btn btn-branded-primary">
26
36
  Redirigir a External Login
27
37
  </button>
28
38
  </form>
@@ -30,5 +40,6 @@
30
40
  </div>
31
41
  </div>
32
42
  </div>
43
+ </div>
33
44
  {% endblock %}
34
45
 
@@ -1,6 +1,6 @@
1
1
  {% extends "base.html" %}
2
2
 
3
- {% block title %}Iniciando {{ branding.name | default('IAToolkit') }} IA...{% endblock %}
3
+ {% block title %}Iniciando {{ branding.name }} IA...{% endblock %}
4
4
 
5
5
  {% block styles %}
6
6
  {% endblock %}
@@ -45,6 +45,8 @@
45
45
  <div id="card-icon" class="ob-icon"><i class="fas fa-lightbulb"></i></div>
46
46
  <h3 id="card-title" class="ob-title">Título de la Tarjeta</h3>
47
47
  <p id="card-text" class="ob-text">Descripción de la tarjeta de capacitación.</p>
48
+ <p id="card-example" class="ob-example"></p>
49
+
48
50
  <div class="ob-nav">
49
51
  <button id="prev-card" class="ob-btn btn-branded-primary" aria-label="Anterior">
50
52
  <i class="fas fa-chevron-left"></i>
@@ -88,6 +90,7 @@
88
90
  icon: '#card-icon',
89
91
  title: '#card-title',
90
92
  text: '#card-text',
93
+ example: '#card-example',
91
94
  dots: '#progress-dots',
92
95
  prev: '#prev-card',
93
96
  next: '#next-card',
@@ -11,7 +11,7 @@ from iatoolkit.services.profile_service import ProfileService
11
11
  from iatoolkit.services.auth_service import AuthService
12
12
  from iatoolkit.services.query_service import QueryService
13
13
  from iatoolkit.services.branding_service import BrandingService
14
- from iatoolkit.services.onboarding_service import OnboardingService
14
+ from iatoolkit.services.configuration_service import ConfigurationService
15
15
  from iatoolkit.services.prompt_manager_service import PromptService
16
16
  from iatoolkit.services.i18n_service import I18nService
17
17
  from iatoolkit.common.util import Utility
@@ -31,7 +31,7 @@ class BaseLoginView(MethodView):
31
31
  jwt_service: JWTService,
32
32
  branding_service: BrandingService,
33
33
  prompt_service: PromptService,
34
- onboarding_service: OnboardingService,
34
+ config_service: ConfigurationService,
35
35
  query_service: QueryService,
36
36
  i18n_service: I18nService,
37
37
  utility: Utility
@@ -41,14 +41,14 @@ class BaseLoginView(MethodView):
41
41
  self.jwt_service = jwt_service
42
42
  self.branding_service = branding_service
43
43
  self.prompt_service = prompt_service
44
- self.onboarding_service = onboarding_service
44
+ self.config_service = config_service
45
45
  self.query_service = query_service
46
46
  self.i18n_service = i18n_service
47
47
  self.utility = utility
48
48
 
49
49
 
50
50
  def _handle_login_path(self,
51
- company: Company,
51
+ company_short_name: str,
52
52
  user_identifier: str,
53
53
  target_url: str,
54
54
  redeem_token: str = None):
@@ -56,13 +56,12 @@ class BaseLoginView(MethodView):
56
56
  Centralized logic to decide between the fast path and the slow path.
57
57
  """
58
58
  # --- Get the company branding and onboarding_cards
59
- branding_data = self.branding_service.get_company_branding(company)
60
- onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
61
- company_short_name = company.short_name
59
+ branding_data = self.branding_service.get_company_branding(company_short_name)
60
+ onboarding_cards = self.config_service.get_configuration(company_short_name, 'onboarding_cards')
62
61
 
63
62
  # this service decides is the context needs to be rebuilt or not
64
63
  prep_result = self.query_service.prepare_context(
65
- company_short_name=company.short_name, user_identifier=user_identifier
64
+ company_short_name=company_short_name, user_identifier=user_identifier
66
65
  )
67
66
 
68
67
  if prep_result.get('rebuild_needed'):
@@ -34,7 +34,7 @@ class ChangePasswordView(MethodView):
34
34
  return render_template('error.html',
35
35
  message=self.i18n_service.t('errors.templates.company_not_found')), 404
36
36
 
37
- branding_data = self.branding_service.get_company_branding(company)
37
+ branding_data = self.branding_service.get_company_branding(company_short_name)
38
38
 
39
39
  try:
40
40
  # Decodificar el token
@@ -66,7 +66,7 @@ class ChangePasswordView(MethodView):
66
66
  return render_template('error.html',
67
67
  message=self.i18n_service.t('errors.templates.company_not_found')), 404
68
68
 
69
- branding_data = self.branding_service.get_company_branding(company)
69
+ branding_data = self.branding_service.get_company_branding(company_short_name)
70
70
  try:
71
71
  # Decodificar el token
72
72
  email = self.serializer.loads(token, salt='password-reset', max_age=3600)
@@ -98,7 +98,6 @@ class ChangePasswordView(MethodView):
98
98
  'change_password.html',
99
99
  token=token,
100
100
  company_short_name=company_short_name,
101
- company=company,
102
101
  branding=branding_data,
103
102
  form_data={"temp_code": temp_code,
104
103
  "new_password": new_password,