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.
- iatoolkit/__init__.py +2 -0
- iatoolkit/base_company.py +1 -20
- iatoolkit/common/routes.py +11 -2
- iatoolkit/common/session_manager.py +2 -0
- iatoolkit/common/util.py +17 -0
- iatoolkit/company_registry.py +1 -2
- iatoolkit/iatoolkit.py +41 -5
- iatoolkit/locales/en.yaml +167 -0
- iatoolkit/locales/es.yaml +163 -0
- iatoolkit/repositories/database_manager.py +3 -3
- iatoolkit/repositories/document_repo.py +1 -1
- iatoolkit/repositories/models.py +2 -3
- iatoolkit/repositories/profile_repo.py +0 -4
- iatoolkit/services/auth_service.py +14 -9
- iatoolkit/services/branding_service.py +32 -22
- iatoolkit/services/configuration_service.py +140 -0
- iatoolkit/services/dispatcher_service.py +20 -18
- iatoolkit/services/document_service.py +5 -2
- iatoolkit/services/excel_service.py +15 -11
- iatoolkit/services/file_processor_service.py +4 -12
- iatoolkit/services/history_service.py +8 -7
- iatoolkit/services/i18n_service.py +104 -0
- iatoolkit/services/jwt_service.py +7 -9
- iatoolkit/services/language_service.py +79 -0
- iatoolkit/services/load_documents_service.py +4 -4
- iatoolkit/services/mail_service.py +9 -4
- iatoolkit/services/onboarding_service.py +10 -4
- iatoolkit/services/profile_service.py +58 -38
- iatoolkit/services/prompt_manager_service.py +20 -16
- iatoolkit/services/query_service.py +15 -14
- iatoolkit/services/sql_service.py +6 -2
- iatoolkit/services/user_feedback_service.py +16 -14
- iatoolkit/static/js/chat_feedback_button.js +57 -87
- iatoolkit/static/js/chat_help_content.js +124 -0
- iatoolkit/static/js/chat_history_button.js +48 -65
- iatoolkit/static/js/chat_main.js +27 -24
- iatoolkit/static/js/chat_reload_button.js +28 -45
- iatoolkit/static/styles/chat_iatoolkit.css +223 -315
- iatoolkit/static/styles/chat_modal.css +63 -97
- iatoolkit/static/styles/chat_public.css +107 -0
- iatoolkit/static/styles/landing_page.css +0 -1
- iatoolkit/templates/_company_header.html +6 -2
- iatoolkit/templates/_login_widget.html +42 -0
- iatoolkit/templates/base.html +34 -19
- iatoolkit/templates/change_password.html +22 -20
- iatoolkit/templates/chat.html +58 -27
- iatoolkit/templates/chat_modals.html +113 -74
- iatoolkit/templates/error.html +12 -13
- iatoolkit/templates/forgot_password.html +11 -7
- iatoolkit/templates/index.html +8 -3
- iatoolkit/templates/login_simulation.html +16 -5
- iatoolkit/templates/onboarding_shell.html +0 -1
- iatoolkit/templates/signup.html +14 -14
- iatoolkit/views/base_login_view.py +12 -1
- iatoolkit/views/change_password_view.py +49 -33
- iatoolkit/views/forgot_password_view.py +20 -19
- iatoolkit/views/help_content_api_view.py +54 -0
- iatoolkit/views/history_api_view.py +13 -9
- iatoolkit/views/home_view.py +30 -38
- iatoolkit/views/init_context_api_view.py +16 -11
- iatoolkit/views/llmquery_api_view.py +38 -26
- iatoolkit/views/login_simulation_view.py +14 -2
- iatoolkit/views/login_view.py +47 -35
- iatoolkit/views/logout_api_view.py +26 -22
- iatoolkit/views/profile_api_view.py +46 -0
- iatoolkit/views/prompt_api_view.py +6 -6
- iatoolkit/views/signup_view.py +26 -24
- iatoolkit/views/user_feedback_api_view.py +19 -18
- iatoolkit/views/verify_user_view.py +30 -29
- {iatoolkit-0.63.1.dist-info → iatoolkit-0.67.0.dist-info}/METADATA +40 -22
- iatoolkit-0.67.0.dist-info/RECORD +120 -0
- iatoolkit-0.67.0.dist-info/licenses/LICENSE +21 -0
- iatoolkit/static/styles/chat_info.css +0 -53
- iatoolkit/templates/header.html +0 -31
- iatoolkit/templates/test.html +0 -9
- iatoolkit-0.63.1.dist-info/RECORD +0 -112
- {iatoolkit-0.63.1.dist-info → iatoolkit-0.67.0.dist-info}/WHEEL +0 -0
- {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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
/*
|
|
108
|
-
|
|
109
|
-
color:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
72
|
+
.star::before {
|
|
73
|
+
content: '★';
|
|
74
|
+
}
|
|
75
|
+
|
|
136
76
|
.star:hover,
|
|
137
77
|
.star.active,
|
|
138
78
|
.star.hover-active {
|
|
139
|
-
color:
|
|
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
|
+
|
|
@@ -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>
|
iatoolkit/templates/base.html
CHANGED
|
@@ -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"
|
|
9
|
-
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css"
|
|
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
|
|
20
|
-
|
|
21
|
-
<
|
|
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
|
-
</
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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 %}
|
|
3
|
+
{% block title %}{{ t('ui.change_password.title') }} - {{ company.name }}{% endblock %}
|
|
4
4
|
|
|
5
|
-
{% block
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
12
|
+
{% block content %}
|
|
13
|
+
<div class="container mt-4">
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
{% include '_navbar.html' %}
|
|
15
|
+
{% include '_company_header.html' %}
|
|
14
16
|
|
|
15
|
-
<!--
|
|
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">
|
|
22
|
-
|
|
23
|
+
<h4 class="branded-form-title">{{ t('ui.change_password.title') }}</h4>
|
|
23
24
|
<p class="text-muted text-center mb-4">
|
|
24
|
-
|
|
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">
|
|
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="
|
|
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">
|
|
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>
|
|
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">
|
|
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">
|
|
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>
|
|
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 %}
|