iatoolkit 0.63.1__py3-none-any.whl → 0.67.0__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 (78) hide show
  1. iatoolkit/__init__.py +2 -0
  2. iatoolkit/base_company.py +1 -20
  3. iatoolkit/common/routes.py +11 -2
  4. iatoolkit/common/session_manager.py +2 -0
  5. iatoolkit/common/util.py +17 -0
  6. iatoolkit/company_registry.py +1 -2
  7. iatoolkit/iatoolkit.py +41 -5
  8. iatoolkit/locales/en.yaml +167 -0
  9. iatoolkit/locales/es.yaml +163 -0
  10. iatoolkit/repositories/database_manager.py +3 -3
  11. iatoolkit/repositories/document_repo.py +1 -1
  12. iatoolkit/repositories/models.py +2 -3
  13. iatoolkit/repositories/profile_repo.py +0 -4
  14. iatoolkit/services/auth_service.py +14 -9
  15. iatoolkit/services/branding_service.py +32 -22
  16. iatoolkit/services/configuration_service.py +140 -0
  17. iatoolkit/services/dispatcher_service.py +20 -18
  18. iatoolkit/services/document_service.py +5 -2
  19. iatoolkit/services/excel_service.py +15 -11
  20. iatoolkit/services/file_processor_service.py +4 -12
  21. iatoolkit/services/history_service.py +8 -7
  22. iatoolkit/services/i18n_service.py +104 -0
  23. iatoolkit/services/jwt_service.py +7 -9
  24. iatoolkit/services/language_service.py +79 -0
  25. iatoolkit/services/load_documents_service.py +4 -4
  26. iatoolkit/services/mail_service.py +9 -4
  27. iatoolkit/services/onboarding_service.py +10 -4
  28. iatoolkit/services/profile_service.py +58 -38
  29. iatoolkit/services/prompt_manager_service.py +20 -16
  30. iatoolkit/services/query_service.py +15 -14
  31. iatoolkit/services/sql_service.py +6 -2
  32. iatoolkit/services/user_feedback_service.py +16 -14
  33. iatoolkit/static/js/chat_feedback_button.js +57 -87
  34. iatoolkit/static/js/chat_help_content.js +124 -0
  35. iatoolkit/static/js/chat_history_button.js +48 -65
  36. iatoolkit/static/js/chat_main.js +27 -24
  37. iatoolkit/static/js/chat_reload_button.js +28 -45
  38. iatoolkit/static/styles/chat_iatoolkit.css +223 -315
  39. iatoolkit/static/styles/chat_modal.css +63 -97
  40. iatoolkit/static/styles/chat_public.css +107 -0
  41. iatoolkit/static/styles/landing_page.css +0 -1
  42. iatoolkit/templates/_company_header.html +6 -2
  43. iatoolkit/templates/_login_widget.html +42 -0
  44. iatoolkit/templates/base.html +34 -19
  45. iatoolkit/templates/change_password.html +22 -20
  46. iatoolkit/templates/chat.html +58 -27
  47. iatoolkit/templates/chat_modals.html +113 -74
  48. iatoolkit/templates/error.html +12 -13
  49. iatoolkit/templates/forgot_password.html +11 -7
  50. iatoolkit/templates/index.html +8 -3
  51. iatoolkit/templates/login_simulation.html +16 -5
  52. iatoolkit/templates/onboarding_shell.html +0 -1
  53. iatoolkit/templates/signup.html +14 -14
  54. iatoolkit/views/base_login_view.py +12 -1
  55. iatoolkit/views/change_password_view.py +49 -33
  56. iatoolkit/views/forgot_password_view.py +20 -19
  57. iatoolkit/views/help_content_api_view.py +54 -0
  58. iatoolkit/views/history_api_view.py +13 -9
  59. iatoolkit/views/home_view.py +30 -38
  60. iatoolkit/views/init_context_api_view.py +16 -11
  61. iatoolkit/views/llmquery_api_view.py +38 -26
  62. iatoolkit/views/login_simulation_view.py +14 -2
  63. iatoolkit/views/login_view.py +47 -35
  64. iatoolkit/views/logout_api_view.py +26 -22
  65. iatoolkit/views/profile_api_view.py +46 -0
  66. iatoolkit/views/prompt_api_view.py +6 -6
  67. iatoolkit/views/signup_view.py +26 -24
  68. iatoolkit/views/user_feedback_api_view.py +19 -18
  69. iatoolkit/views/verify_user_view.py +30 -29
  70. {iatoolkit-0.63.1.dist-info → iatoolkit-0.67.0.dist-info}/METADATA +40 -22
  71. iatoolkit-0.67.0.dist-info/RECORD +120 -0
  72. iatoolkit-0.67.0.dist-info/licenses/LICENSE +21 -0
  73. iatoolkit/static/styles/chat_info.css +0 -53
  74. iatoolkit/templates/header.html +0 -31
  75. iatoolkit/templates/test.html +0 -9
  76. iatoolkit-0.63.1.dist-info/RECORD +0 -112
  77. {iatoolkit-0.63.1.dist-info → iatoolkit-0.67.0.dist-info}/WHEEL +0 -0
  78. {iatoolkit-0.63.1.dist-info → iatoolkit-0.67.0.dist-info}/top_level.txt +0 -0
@@ -1,54 +1,4 @@
1
- /* ######################################################### */
2
1
  /* Estilos generales para modales */
3
- /* ######################################################### */
4
-
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
- background-color: var(--brand-text-on-primary);
23
- color: var(--brand-primary-color);
24
- border-color: var(--brand-primary-color);
25
- }
26
-
27
- .btn-branded-secondary {
28
- background-color: var(--brand-secondary-color);
29
- border-color: var(--brand-secondary-color);
30
- color: var(--brand-text-on-secondary);
31
- }
32
- .btn-branded-secondary:hover {
33
- background-color: var(--brand-text-on-secondary);
34
- color: var(--brand-secondary-color);
35
- border-color: var(--brand-secondary-color);
36
- }
37
-
38
- /* Estilos para alertas informativas personalizadas */
39
- .alert-branded-info {
40
- background-color: var(--brand-info-bg);
41
- color: var(--brand-info-text);
42
- border-color: var(--brand-info-border);
43
- }
44
- .alert-branded-info strong,
45
- .alert-branded-info .alert-link {
46
- color: inherit;
47
- }
48
- .alert-branded-info .bi { /* Asegura que los iconos también tomen el color */
49
- color: inherit;
50
- }
51
-
52
2
 
53
3
  /* Título del modal */
54
4
  .modal-title{
@@ -56,7 +6,6 @@
56
6
  font-weight: bold;
57
7
  }
58
8
 
59
-
60
9
  /* Estilos del header del modal*/
61
10
  .modal-header {
62
11
  display: flex;
@@ -70,6 +19,7 @@
70
19
  margin: 0;
71
20
  padding: 0;
72
21
  flex: 1;
22
+ color: inherit;
73
23
  }
74
24
 
75
25
  /* Estilos del botón de cerrar del modal*/
@@ -79,49 +29,36 @@
79
29
  margin-left: auto;
80
30
  }
81
31
 
82
- /* ######################################################### */
83
- /* Modal de historial */
84
- /* ######################################################### */
85
-
86
- /* Encabezado de tabla con branding */
87
- .thead-branded th {
88
- background-color: var(--brand-primary-color);
89
- color: var(--brand-text-on-primary);
90
- font-size: 16px;
91
- font-weight: bold;
32
+ /* Estilos del header del modal con branding */
33
+ .modal-header.branded {
34
+ background-color: var(--brand-modal-header-bg);
35
+ color: var(--brand-modal-header-text);
36
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
92
37
  }
93
-
94
-
95
- #history-content .table td:nth-child(1) { width: 5%; }
96
- #history-content .table td:nth-child(2) { width: 23%; }
97
-
98
- #history-content .table td:nth-child(3) {
99
- width: auto; /* Columna de la consulta - ocupa el resto */
38
+ .modal-header.branded .btn-close {
39
+ filter: invert(1) grayscale(100%) brightness(200%); /* Hace el botón de cerrar visible en fondos oscuros */
100
40
  }
101
41
 
102
- /* Evita el salto de línea en la celda de la fecha */
103
- #historyModal .date-cell {
104
- white-space: nowrap;
105
- }
106
42
 
107
- /* Estilo para el icono de copiar/editar en cada fila */
108
- #historyModal .copy-query-icon {
109
- color: var(--brand-secondary-color, #6c757d); /* Usa el color secundario de la marca */
110
- text-decoration: none;
111
- opacity: 0.6;
112
- transition: opacity 0.2s ease-in-out;
43
+ /* Tabla con el resultado del historial */
44
+ .thead-branded th {
45
+ background-color: #e9ecef; /* Un gris claro estándar de Bootstrap */
46
+ color: #212529; /* El color de texto oscuro por defecto */
47
+ font-size: 16px;
48
+ font-weight: bold;
113
49
  }
114
-
115
- #historyModal .copy-query-icon:hover {
116
- opacity: 1; /* El icono se vuelve completamente opaco al pasar el ratón */
117
- cursor: pointer; /* Asegura que el cursor cambie a una mano */
50
+ .col-icon {
51
+ width: 1%;
118
52
  }
119
53
 
120
- /* ######################################################### */
121
54
  /* Modal de feedback */
122
- /* ######################################################### */
123
-
124
- /* Contenedor de calificación del modal de feedback */
55
+ .rating-stars {
56
+ display: flex;
57
+ justify-content: center;
58
+ gap: 5px;
59
+ margin-bottom: 15px;
60
+ padding-top: 5px;
61
+ }
125
62
 
126
63
  /* Estilos de las estrellas del modal de feedback */
127
64
  .star {
@@ -132,16 +69,51 @@
132
69
  margin: 0 2px;
133
70
  }
134
71
 
135
- /* Estilos de las estrellas del modal de feedback al pasar el mouse */
72
+ .star::before {
73
+ content: '★';
74
+ }
75
+
136
76
  .star:hover,
137
77
  .star.active,
138
78
  .star.hover-active {
139
- color: #ffc107;
79
+ color: var(--brand-primary-color);
80
+ }
81
+
82
+ /* model de help */
83
+ .modal-body .accordion-button:not(.collapsed) {
84
+ background-color: var(--brand-primary-color);
85
+ color: var(--brand-text-on-primary);
86
+ font-weight: 600;
87
+ box-shadow: none;
88
+ }
89
+
90
+ /* Estilo para el anillo de foco, aplicado ÚNICAMENTE cuando el botón está CERRADO y tiene foco. */
91
+ .modal-body .accordion-button.collapsed:focus {
92
+ background-color: #fff; /* Asegura fondo blanco al hacer foco en un item cerrado */
93
+ border-color: transparent; /* Evita bordes no deseados */
94
+ /* La única regla que debe estar aquí es la que dibuja el anillo de foco. */
95
+ box-shadow: 0 0 0 0.25rem rgba(var(--brand-primary-color-rgb), 0.25);
96
+ }
97
+
98
+ .icon-spaced {
99
+ margin-right: 10px;
100
+ }
101
+
102
+ .text-muted{
103
+ font-size:16px;
104
+ text-align: justify;
105
+ }
106
+
107
+ .feedback-text{
108
+ font-size: 16px;
140
109
  }
141
110
 
142
- /* ######################################################### */
143
111
  /* Modal de listado de archivos */
144
- /* ######################################################### */
112
+ /* Estilos del nombre del archivo del modal de archivos y ordenar icono */
113
+ .file-name-modal {
114
+ flex: 1;
115
+ margin-right: 10px;
116
+ }
145
117
 
146
118
  /* Para el icono de eliminar del modal */
147
119
  .remove-file-btn i {
@@ -155,13 +127,7 @@
155
127
  align-items: center;
156
128
  }
157
129
 
158
- /* Estilos del nombre del archivo del modal de archivos y ordenar icono */
159
- .file-name-modal {
160
- flex: 1;
161
- margin-right: 10px;
162
- }
163
-
164
130
  /* Estilos del botón de eliminar del modal de archivos y ordenar icono */
165
131
  .remove-file-btn {
166
132
  flex-shrink: 0;
167
- }
133
+ }
@@ -0,0 +1,107 @@
1
+ /* Estos estilos son para las paginas publicas: home, signup, olvide la clave, etc */
2
+
3
+ /* --- Encabezado (top) de company --- */
4
+ .custom-company-header {
5
+ height: 78px;
6
+ margin-bottom: 20px;
7
+ padding: 0 1.5rem; /* Padding interno para que el texto no toque los bordes */
8
+ border-radius: 0.375rem; /* Bordes redondeados para que coincida con los formularios */
9
+
10
+ /* Los estilos de color y sombra se mantienen */
11
+ background-color: var(--brand-header-bg);
12
+ color: var(--brand-header-text);
13
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); /* Sombra ligeramente más suave */
14
+ }
15
+
16
+ /* Estilo específico para el nombre de la marca en el encabezado (Letra más grande) */
17
+ .custom-company-header .brand-name {
18
+ font-size: 1.8rem; /* Tamaño de fuente aumentado */
19
+ font-weight: 600;
20
+ color: inherit;
21
+ text-decoration: none;
22
+ transition: opacity 0.2s ease-in-out;
23
+ }
24
+
25
+ /* Efecto hover para el enlace del nombre de la marca */
26
+ .custom-company-header .brand-name:hover {
27
+ opacity: 0.85;
28
+ }
29
+
30
+ /* Estilo para el texto "Powered by" --- */
31
+ .custom-company-header .powered-by {
32
+ font-size: 0.9rem;
33
+ font-weight: 400;
34
+ opacity: 0.75; /* Menos prominente que el nombre de la marca */
35
+ color: inherit;
36
+ }
37
+
38
+ /* --- Estilo para el enlace de IAToolkit --- */
39
+ .custom-company-header .iatoolkit-link {
40
+ color: inherit; /* Hereda el color del texto padre */
41
+ text-decoration: none; /* ¡Elimina el subrayado! */
42
+ font-weight: 600; /* Un poco más de peso para diferenciarlo */
43
+ transition: opacity 0.2s ease-in-out;
44
+ }
45
+
46
+ .custom-company-header .form-container {
47
+ display: flex;
48
+ flex-direction: column;
49
+ gap: 1rem;
50
+ }
51
+
52
+ /* titulo en home */
53
+ .home-title {
54
+ font-size: 3.2rem;
55
+ font-weight: 800;
56
+ line-height: 1.2;
57
+ color: var(--brand-primary-color);
58
+ }
59
+ .list-example {
60
+ display: block; /* Coloca el ejemplo en su propia línea */
61
+ font-size: 0.9rem; /* Lo hace ligeramente más pequeño */
62
+ color: #6c757d; /* Color gris (muted) para texto secundario */
63
+ font-style: italic; /* Cursiva para diferenciarlo */
64
+ padding-left: 1.75rem; /* Lo indenta para alinearlo con el texto del tema */
65
+ margin-top: 0.25rem; /* Pequeño espacio superior */
66
+ }
67
+
68
+ .text-brand-primary {
69
+ font-weight: 800;
70
+ color: var(--brand-primary-color);
71
+ }
72
+
73
+ /* contenedor de formularios: login, signup, forgot password, etc. */
74
+ .branded-form-container {
75
+ background-color: #ffffff;
76
+ border: 1px solid #dee2e6;
77
+ border-top: 4px solid #adb5bd;
78
+ border-radius: 0.375rem;
79
+ padding: 2rem;
80
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
81
+ }
82
+
83
+ .branded-form-label {
84
+ font-size: 0.85rem;
85
+ font-weight: 600;
86
+ color: #495057; /* Un gris oscuro profesional */
87
+ text-transform: uppercase;
88
+ letter-spacing: 0.05em; /* Un poco de espacio extra entre letras */
89
+ margin-bottom: 0.3rem;
90
+ display: block;
91
+ }
92
+
93
+ /* Efecto de foco brandeado para todos los form-control */
94
+ .form-control:focus {
95
+ border-color: var(--brand-primary-color);
96
+ box-shadow: 0 0 0 0.25rem rgba(var(--brand-primary-color-rgb), 0.25); /* Usa la variable RGB para el shadow */
97
+ }
98
+
99
+ .branded-form-title {
100
+ color: var(--brand-primary-color);
101
+ font-size: 1.75rem; /* Un tamaño más prominente */
102
+ font-weight: 700; /* Equivalente a fw-bold de Bootstrap */
103
+ text-align: center;
104
+ margin-bottom: 1.5rem; /* Espacio consistente debajo del título */
105
+ }
106
+
107
+
@@ -86,7 +86,6 @@ body {
86
86
  color: var(--website-primary-color);
87
87
  }
88
88
 
89
- /* --- Sección de Características (Features) --- */
90
89
  .features-section {
91
90
  padding: 5rem 0;
92
91
  background-color: var(--website-light-bg);
@@ -1,16 +1,20 @@
1
1
  {# El div principal ahora es un contenedor y tiene los estilos y clases de alineación #}
2
2
  <div class="custom-company-header container d-flex justify-content-between align-items-center">
3
3
 
4
+ {% if company_short_name and branding %}
4
5
  <a href="{{ url_for('home', company_short_name=company_short_name) }}"
5
6
  class="brand-name"
6
7
  style="{{ branding.primary_text_style }}">
7
8
  {{ branding.name }} IA
8
9
  </a>
9
-
10
+ {% else %}
11
+ <span class="brand-name">
12
+ IAToolkit
13
+ </span>
14
+ {% endif %}
10
15
 
11
16
  {# Texto "Powered by" con enlace a iatoolkit.com #}
12
17
  <span class="powered-by">
13
18
  Powered by <a href="{{ url_for('index') }}" rel="noopener noreferrer" class="iatoolkit-link">IAToolkit</a>
14
19
  </span>
15
-
16
20
  </div>
@@ -0,0 +1,42 @@
1
+ <div class="branded-form-container">
2
+ <!-- 1. Encabezado de Marketing -->
3
+ <div class="text-center mb-4">
4
+ <p class="text-muted widget-intro-text">
5
+ {{ t('ui.login_widget.welcome_message') }}
6
+ </p>
7
+ </div>
8
+
9
+ <!-- 2. Formulario de Inicio de Sesión -->
10
+ <form id="login-form"
11
+ action="{{ url_for('login', company_short_name=company_short_name) }}"
12
+ method="post">
13
+ <div class="mb-3">
14
+ <label for="email" class="form-label d-block">{{ t('ui.signup.email_label') }}</label>
15
+ <input type="email" id="email" name="email" class="form-control"
16
+ required value="{{ form_data.email if form_data is defined else '' }}">
17
+ </div>
18
+ <div class="mb-3">
19
+ <label for="password" class="form-label d-block">{{ t('ui.signup.password_label') }}</label>
20
+ <input type="password" id="password" name="password"
21
+ class="form-control" required>
22
+ </div>
23
+ <button type="submit" class="btn btn-branded-primary w-100 fw-bold py-2">
24
+ {{ t('ui.login_widget.login_button') }}
25
+ </button>
26
+ </form>
27
+
28
+ <!-- 3. Nueva Sección de Registro más Atractiva -->
29
+ <div class="mt-4 pt-3 text-center" style="border-top: 1px solid #e0e0e0;">
30
+ <span class="text-muted small">{{ t('ui.login_widget.no_account_prompt') }}</span>
31
+ <a href="{{ url_for('signup', company_short_name=company_short_name) }}" id="signup-link"
32
+ class="fw-bold ms-1 text-decoration-none" style="color: var(--brand-primary-color);">
33
+ {{ t('ui.login_widget.signup_link') }}</a>
34
+ </div>
35
+
36
+ <!-- 4. Enlace de Recuperación de Contraseña (más sutil) -->
37
+ <div class="text-center mt-2">
38
+ <a href="{{ url_for('forgot_password', company_short_name=company_short_name) }}" class="text-decoration-none text-muted" style="font-size: 0.8rem;">
39
+ {{ t('ui.login_widget.forgot_password_link') }}
40
+ </a>
41
+ </div>
42
+ </div>
@@ -4,11 +4,13 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
6
  <title>{% block title %}Chatbot{% endblock %}</title>
7
+
7
8
  <!-- Bootstrap 5 CSS -->
8
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet">
9
- <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
9
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css">
10
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" >
10
11
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/filepond/dist/filepond.min.css">
11
12
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
13
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" />
12
14
  <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_iatoolkit.css', _external=True) }}">
13
15
  <link rel="stylesheet" href="{{ url_for('static', filename='styles/onboarding.css', _external=True) }}">
14
16
  <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_modal.css', _external=True) }}">
@@ -16,32 +18,45 @@
16
18
 
17
19
  {% block styles %}{% endblock %}
18
20
  </head>
19
- <body class="d-flex flex-column p-3" style="min-height: 100vh;">
20
-
21
- <main class="d-flex flex-column flex-grow-1">
21
+ <body>
22
+ <!-- El "Ancla": Envolvemos el contenido en un div con un ID y estilo. -->
23
+ <div id="page-content-wrapper" style="position: relative;">
22
24
  {% block content %}{% endblock %}
23
- </main>
24
-
25
+ </div>
25
26
 
26
27
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
27
28
  <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
28
29
  <script src="https://cdn.jsdelivr.net/npm/filepond/dist/filepond.min.js"></script>
29
30
  <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
30
-
31
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
31
32
 
32
33
  <!-- Mostrar alertas SweetAlert2 si existe el mensaje -->
33
34
  <script>
34
- {% if alert_message %}
35
- Swal.fire({
36
- text: "{{ alert_message }}", // Mensaje pasado desde Flask
37
- icon: "{{ alert_icon | default('error') }}", // Ícono por defecto "error"
38
- confirmButtonText: "OK",
39
- cancelButtonText: 'Cancelar',
40
- customClass: {
41
- confirmButton: 'custom-confirm-button', // Clase personalizada para el botón
42
- cancelButton: 'custom-cancel-button' // Clase personalizada para el botón de cancelar
43
- }
44
- });
35
+ // Configuración global de Toastr
36
+ toastr.options = {
37
+ "closeButton": true,
38
+ "progressBar": true,
39
+ "positionClass": "toast-bottom-right",
40
+ "preventDuplicates": true,
41
+ "timeOut": "7000",
42
+ "extendedTimeOut": "1000",
43
+ "tapToDismiss": false,
44
+ "target": "#page-content-wrapper"
45
+ };
46
+
47
+ {% if flashed_messages %}
48
+ {% for category, message in flashed_messages %}
49
+ var toastClass = 'toast-info'; // default class
50
+ if ('{{ category }}' === 'error') {
51
+ toastClass = 'toast-error';
52
+ } else if ('{{ category }}' === 'success') {
53
+ toastClass = 'toast-success';
54
+ }
55
+
56
+ // Llama a Toastr usando la opción 'toastClass' para aplicar nuestro estilo
57
+ toastr.info("{{ message }}", null, { "toastClass": "toast " + toastClass });
58
+
59
+ {% endfor %}
45
60
  {% endif %}
46
61
  </script>
47
62
 
@@ -1,59 +1,59 @@
1
1
  {% extends "base.html" %}
2
2
 
3
- {% block title %}Cambiar Contraseña - {{ company.name }}{% endblock %}
3
+ {% block title %}{{ t('ui.change_password.title') }} - {{ company.name }}{% endblock %}
4
4
 
5
- {% block content %}
6
- <!-- 1. Incluimos los estilos de branding reutilizables -->
7
- {% include '_branding_styles.html' %}
5
+ {% block styles %}
6
+ <style>
7
+ {{ branding.css_variables | safe }}
8
+ </style>
9
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_public.css') }}">
10
+ {% endblock %}
8
11
 
9
- <!-- Enlazamos la hoja de estilos de la landing page para reutilizar estilos -->
10
- <link rel="stylesheet" href="{{ iatoolkit_base_url }}/static/styles/landing_page.css">
12
+ {% block content %}
13
+ <div class="container mt-4">
11
14
 
12
- <!-- 2. Incluimos la barra de navegación reutilizable -->
13
- {% include '_navbar.html' %}
15
+ {% include '_company_header.html' %}
14
16
 
15
- <!-- 3. Sección contenedora para centrar el contenido -->
17
+ <!-- Sección contenedora para centrar el contenido -->
16
18
  <section class="hero-section">
17
19
  <div class="container">
18
20
  <div class="row justify-content-center">
19
21
  <div class="col-lg-6 col-md-8">
20
22
  <div class="branded-form-container">
21
- <h4 class="branded-form-title">Crear Nueva Contraseña</h4>
22
-
23
+ <h4 class="branded-form-title">{{ t('ui.change_password.title') }}</h4>
23
24
  <p class="text-muted text-center mb-4">
24
- Estás cambiando la contraseña para <strong>{{ email }}</strong>.
25
+ {{ t('ui.change_password.subtitle', email=email) | safe }}
25
26
  </p>
26
27
 
27
28
  <form action="{{ url_for('change_password', company_short_name=company_short_name, token=token) }}" method="post">
28
29
 
29
- <!-- CAMPO RESTAURADO: Código Temporal -->
30
30
  <div class="mb-3">
31
- <label for="temp_code" class="form-label text-secondary">Código Temporal</label>
31
+ <label for="temp_code" class="form-label text-secondary">{{ t('ui.change_password.temp_code_label') }}</label>
32
32
  <input type="text" id="temp_code" name="temp_code" class="form-control"
33
33
  required value="{{ form_data.temp_code if form_data else '' }}"
34
- placeholder="Revisa tu correo electrónico">
34
+ placeholder="{{ t('ui.change_password.temp_code_placeholder') }}">
35
35
  </div>
36
36
 
37
37
  <div class="mb-3">
38
- <label for="new_password" class="form-label text-secondary">Nueva Contraseña</label>
38
+ <label for="new_password" class="form-label text-secondary">{{ t('ui.change_password.new_password_label') }}</label>
39
39
  <input type="password" id="new_password" name="new_password" class="form-control" required>
40
40
  <div class="d-flex align-items-start text-muted mt-2" style="font-size: 0.8rem;">
41
41
  <i class="bi bi-info-circle me-2" style="font-size: 0.9rem; line-height: 1.4;"></i>
42
- <span>Debe contener al menos 8 caracteres, mayúscula, minúscula, número y un carácter especial.</span>
42
+ <span>{{ t('ui.change_password.password_instructions') }}</span>
43
43
  </div>
44
44
  </div>
45
45
 
46
46
  <div class="mb-3">
47
- <label for="confirm_password" class="form-label text-secondary">Confirmar Nueva Contraseña</label>
47
+ <label for="confirm_password" class="form-label text-secondary">{{ t('ui.change_password.confirm_password_label') }}</label>
48
48
  <input type="password" id="confirm_password" name="confirm_password" class="form-control" required>
49
49
  </div>
50
50
 
51
- <button type="submit" class="btn btn-branded-primary w-100 fw-bold py-2 mt-3">Guardar Contraseña</button>
51
+ <button type="submit" class="btn btn-branded-primary w-100 fw-bold py-2 mt-3">{{ t('ui.change_password.save_button') }}</button>
52
52
  </form>
53
53
 
54
54
  <div class="text-center mt-4 pt-3" style="border-top: 1px solid #e0e0e0;">
55
55
  <a href="{{ url_for('home', company_short_name=company_short_name) }}" class="text-muted text-decoration-none fw-semibold">
56
- <i class="bi bi-arrow-left me-1"></i>Volver al inicio
56
+ <i class="bi bi-arrow-left me-1"></i>{{ t('ui.change_password.back_to_home') }}
57
57
  </a>
58
58
  </div>
59
59
  </div>
@@ -61,4 +61,6 @@
61
61
  </div>
62
62
  </div>
63
63
  </section>
64
+ </div>
65
+
64
66
  {% endblock %}