iatoolkit 0.11.0__py3-none-any.whl → 0.71.2__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.
- iatoolkit/__init__.py +2 -6
- iatoolkit/base_company.py +9 -29
- iatoolkit/cli_commands.py +1 -1
- iatoolkit/common/routes.py +96 -52
- iatoolkit/common/session_manager.py +2 -1
- iatoolkit/common/util.py +17 -27
- iatoolkit/company_registry.py +1 -2
- iatoolkit/iatoolkit.py +97 -53
- iatoolkit/infra/llm_client.py +15 -20
- iatoolkit/infra/llm_proxy.py +38 -10
- iatoolkit/infra/openai_adapter.py +1 -1
- iatoolkit/infra/redis_session_manager.py +48 -2
- iatoolkit/locales/en.yaml +167 -0
- iatoolkit/locales/es.yaml +163 -0
- iatoolkit/repositories/database_manager.py +23 -3
- iatoolkit/repositories/document_repo.py +1 -1
- iatoolkit/repositories/models.py +35 -10
- iatoolkit/repositories/profile_repo.py +3 -2
- iatoolkit/repositories/vs_repo.py +26 -20
- iatoolkit/services/auth_service.py +193 -0
- iatoolkit/services/branding_service.py +70 -25
- iatoolkit/services/company_context_service.py +155 -0
- iatoolkit/services/configuration_service.py +133 -0
- iatoolkit/services/dispatcher_service.py +80 -105
- iatoolkit/services/document_service.py +5 -2
- iatoolkit/services/embedding_service.py +146 -0
- iatoolkit/services/excel_service.py +30 -26
- iatoolkit/services/file_processor_service.py +4 -12
- iatoolkit/services/history_service.py +7 -16
- iatoolkit/services/i18n_service.py +104 -0
- iatoolkit/services/jwt_service.py +18 -29
- iatoolkit/services/language_service.py +83 -0
- iatoolkit/services/load_documents_service.py +100 -113
- iatoolkit/services/mail_service.py +9 -4
- iatoolkit/services/profile_service.py +152 -76
- iatoolkit/services/prompt_manager_service.py +20 -16
- iatoolkit/services/query_service.py +208 -96
- iatoolkit/services/search_service.py +11 -4
- iatoolkit/services/sql_service.py +57 -25
- iatoolkit/services/tasks_service.py +1 -1
- iatoolkit/services/user_feedback_service.py +72 -34
- iatoolkit/services/user_session_context_service.py +112 -54
- iatoolkit/static/images/fernando.jpeg +0 -0
- iatoolkit/static/js/chat_feedback_button.js +80 -0
- iatoolkit/static/js/chat_help_content.js +124 -0
- iatoolkit/static/js/chat_history_button.js +110 -0
- iatoolkit/static/js/chat_logout_button.js +36 -0
- iatoolkit/static/js/chat_main.js +135 -222
- iatoolkit/static/js/chat_onboarding_button.js +103 -0
- iatoolkit/static/js/chat_prompt_manager.js +94 -0
- iatoolkit/static/js/chat_reload_button.js +35 -0
- iatoolkit/static/styles/chat_iatoolkit.css +289 -210
- iatoolkit/static/styles/chat_modal.css +63 -77
- iatoolkit/static/styles/chat_public.css +107 -0
- iatoolkit/static/styles/landing_page.css +182 -0
- iatoolkit/static/styles/onboarding.css +176 -0
- iatoolkit/system_prompts/query_main.prompt +5 -22
- iatoolkit/templates/_company_header.html +20 -0
- iatoolkit/templates/_login_widget.html +42 -0
- iatoolkit/templates/base.html +40 -20
- iatoolkit/templates/change_password.html +57 -36
- iatoolkit/templates/chat.html +180 -86
- iatoolkit/templates/chat_modals.html +138 -68
- iatoolkit/templates/error.html +44 -8
- iatoolkit/templates/forgot_password.html +40 -23
- iatoolkit/templates/index.html +145 -0
- iatoolkit/templates/login_simulation.html +45 -0
- iatoolkit/templates/onboarding_shell.html +107 -0
- iatoolkit/templates/signup.html +63 -65
- iatoolkit/views/base_login_view.py +91 -0
- iatoolkit/views/change_password_view.py +56 -31
- iatoolkit/views/embedding_api_view.py +65 -0
- iatoolkit/views/external_login_view.py +61 -28
- iatoolkit/views/{file_store_view.py → file_store_api_view.py} +10 -3
- iatoolkit/views/forgot_password_view.py +27 -21
- iatoolkit/views/help_content_api_view.py +54 -0
- iatoolkit/views/history_api_view.py +56 -0
- iatoolkit/views/home_view.py +50 -23
- iatoolkit/views/index_view.py +14 -0
- iatoolkit/views/init_context_api_view.py +74 -0
- iatoolkit/views/llmquery_api_view.py +58 -0
- iatoolkit/views/login_simulation_view.py +93 -0
- iatoolkit/views/login_view.py +130 -37
- iatoolkit/views/logout_api_view.py +49 -0
- iatoolkit/views/profile_api_view.py +46 -0
- iatoolkit/views/{prompt_view.py → prompt_api_view.py} +10 -10
- iatoolkit/views/signup_view.py +41 -36
- iatoolkit/views/{tasks_view.py → tasks_api_view.py} +10 -36
- iatoolkit/views/tasks_review_api_view.py +55 -0
- iatoolkit/views/user_feedback_api_view.py +60 -0
- iatoolkit/views/verify_user_view.py +34 -29
- {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/METADATA +41 -23
- iatoolkit-0.71.2.dist-info/RECORD +122 -0
- iatoolkit-0.71.2.dist-info/licenses/LICENSE +21 -0
- iatoolkit/common/auth.py +0 -200
- iatoolkit/static/images/arrow_up.png +0 -0
- iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
- iatoolkit/static/images/logo_clinica.png +0 -0
- iatoolkit/static/images/logo_iatoolkit.png +0 -0
- iatoolkit/static/images/logo_maxxa.png +0 -0
- iatoolkit/static/images/logo_notaria.png +0 -0
- iatoolkit/static/images/logo_tarjeta.png +0 -0
- iatoolkit/static/images/logo_umayor.png +0 -0
- iatoolkit/static/images/upload.png +0 -0
- iatoolkit/static/js/chat_feedback.js +0 -115
- iatoolkit/static/js/chat_history.js +0 -117
- iatoolkit/static/styles/chat_info.css +0 -53
- iatoolkit/templates/header.html +0 -31
- iatoolkit/templates/home.html +0 -199
- iatoolkit/templates/login.html +0 -43
- iatoolkit/templates/test.html +0 -9
- iatoolkit/views/chat_token_request_view.py +0 -98
- iatoolkit/views/chat_view.py +0 -58
- iatoolkit/views/download_file_view.py +0 -58
- iatoolkit/views/external_chat_login_view.py +0 -95
- iatoolkit/views/history_view.py +0 -57
- iatoolkit/views/llmquery_view.py +0 -65
- iatoolkit/views/tasks_review_view.py +0 -83
- iatoolkit/views/user_feedback_view.py +0 -74
- iatoolkit-0.11.0.dist-info/RECORD +0 -110
- {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/WHEEL +0 -0
- {iatoolkit-0.11.0.dist-info → iatoolkit-0.71.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{# El div principal ahora es un contenedor y tiene los estilos y clases de alineación #}
|
|
2
|
+
<div class="custom-company-header container d-flex justify-content-between align-items-center">
|
|
3
|
+
|
|
4
|
+
{% if company_short_name and branding %}
|
|
5
|
+
<a href="{{ url_for('home', company_short_name=company_short_name) }}"
|
|
6
|
+
class="brand-name"
|
|
7
|
+
style="{{ branding.primary_text_style }}">
|
|
8
|
+
{{ branding.name }} IA
|
|
9
|
+
</a>
|
|
10
|
+
{% else %}
|
|
11
|
+
<span class="brand-name">
|
|
12
|
+
IAToolkit
|
|
13
|
+
</span>
|
|
14
|
+
{% endif %}
|
|
15
|
+
|
|
16
|
+
{# Texto "Powered by" con enlace a iatoolkit.com #}
|
|
17
|
+
<span class="powered-by">
|
|
18
|
+
Powered by <a href="{{ url_for('index') }}" rel="noopener noreferrer" class="iatoolkit-link">IAToolkit</a>
|
|
19
|
+
</span>
|
|
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,39 +4,59 @@
|
|
|
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">
|
|
12
|
-
<link rel="stylesheet" href="
|
|
13
|
-
<link rel="stylesheet" href="{{ url_for('static', filename='styles/
|
|
14
|
-
<link rel="stylesheet" href="{{ url_for('static', filename='styles/
|
|
13
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css" />
|
|
14
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_iatoolkit.css', _external=True) }}">
|
|
15
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles/onboarding.css', _external=True) }}">
|
|
16
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_modal.css', _external=True) }}">
|
|
17
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles/llm_output.css', _external=True) }}">
|
|
18
|
+
|
|
19
|
+
{% block styles %}{% endblock %}
|
|
15
20
|
</head>
|
|
16
|
-
<body
|
|
17
|
-
|
|
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;">
|
|
18
24
|
{% block content %}{% endblock %}
|
|
19
|
-
</
|
|
25
|
+
</div>
|
|
20
26
|
|
|
21
27
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
|
|
22
28
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
|
23
29
|
<script src="https://cdn.jsdelivr.net/npm/filepond/dist/filepond.min.js"></script>
|
|
24
30
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
25
|
-
|
|
31
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
|
26
32
|
|
|
27
33
|
<!-- Mostrar alertas SweetAlert2 si existe el mensaje -->
|
|
28
34
|
<script>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
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 %}
|
|
40
60
|
{% endif %}
|
|
41
61
|
</script>
|
|
42
62
|
|
|
@@ -1,45 +1,66 @@
|
|
|
1
1
|
{% extends "base.html" %}
|
|
2
2
|
|
|
3
|
-
{% block title %}
|
|
3
|
+
{% block title %}{{ t('ui.change_password.title') }} - {{ branding.name }} {% endblock %}
|
|
4
|
+
|
|
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 %}
|
|
4
11
|
|
|
5
12
|
{% block content %}
|
|
6
|
-
<div class="container
|
|
7
|
-
<div class="col-11 col-md-8 col-lg-5 border rounded p-3 shadow-sm">
|
|
8
|
-
<h4 class="text-muted fw-semibold text-start mb-3">Cambiar Contraseña</h4>
|
|
9
|
-
<h6 class="text-muted text-start mb-4">{{ email }}</h6>
|
|
10
|
-
|
|
11
|
-
<form action="{{ url_for('change_password', company_short_name=company_short_name, token=token) }}" method="post">
|
|
12
|
-
<div class="mb-3">
|
|
13
|
-
<label for="temp_code" class="form-label text-muted">Código Temporal recibido</label>
|
|
14
|
-
<input type="text" name="temp_code" id="temp_code"
|
|
15
|
-
class="form-control text-muted" required
|
|
16
|
-
autocomplete="off"
|
|
17
|
-
value="{{ form_data.temp_code if form_data else '' }}">
|
|
18
|
-
</div>
|
|
19
|
-
<div class="mb-3">
|
|
20
|
-
<label for="new_password" class="form-label text-muted">Nueva Contraseña</label>
|
|
21
|
-
<input type="password" name="new_password" id="new_password"
|
|
22
|
-
class="form-control text-muted" required
|
|
23
|
-
value="{{ form_data.new_password if form_data else '' }}">
|
|
24
|
-
<small class="form-text text-muted">
|
|
25
|
-
La contraseña debe contener al menos 8 caracteres, una letra mayúscula, una letra minúscula, un número y un carácter especial.
|
|
26
|
-
</small>
|
|
13
|
+
<div class="container mt-4">
|
|
27
14
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
{% include '_company_header.html' %}
|
|
16
|
+
|
|
17
|
+
<!-- Sección contenedora para centrar el contenido -->
|
|
18
|
+
<section class="hero-section">
|
|
19
|
+
<div class="container">
|
|
20
|
+
<div class="row justify-content-center">
|
|
21
|
+
<div class="col-lg-6 col-md-8">
|
|
22
|
+
<div class="branded-form-container">
|
|
23
|
+
<h4 class="branded-form-title">{{ t('ui.change_password.title') }}</h4>
|
|
24
|
+
<p class="text-muted text-center mb-4">
|
|
25
|
+
{{ t('ui.change_password.subtitle', email=email) | safe }}
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
<form action="{{ url_for('change_password', company_short_name=company_short_name, token=token) }}" method="post">
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
<div class="mb-3">
|
|
31
|
+
<label for="temp_code" class="form-label text-secondary">{{ t('ui.change_password.temp_code_label') }}</label>
|
|
32
|
+
<input type="text" id="temp_code" name="temp_code" class="form-control"
|
|
33
|
+
required value="{{ form_data.temp_code if form_data else '' }}"
|
|
34
|
+
placeholder="{{ t('ui.change_password.temp_code_placeholder') }}">
|
|
35
|
+
</div>
|
|
41
36
|
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
<div class="mb-3">
|
|
38
|
+
<label for="new_password" class="form-label text-secondary">{{ t('ui.change_password.new_password_label') }}</label>
|
|
39
|
+
<input type="password" id="new_password" name="new_password" class="form-control" required>
|
|
40
|
+
<div class="d-flex align-items-start text-muted mt-2" style="font-size: 0.8rem;">
|
|
41
|
+
<i class="bi bi-info-circle me-2" style="font-size: 0.9rem; line-height: 1.4;"></i>
|
|
42
|
+
<span>{{ t('ui.change_password.password_instructions') }}</span>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="mb-3">
|
|
47
|
+
<label for="confirm_password" class="form-label text-secondary">{{ t('ui.change_password.confirm_password_label') }}</label>
|
|
48
|
+
<input type="password" id="confirm_password" name="confirm_password" class="form-control" required>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
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
|
+
</form>
|
|
53
|
+
|
|
54
|
+
<div class="text-center mt-4 pt-3" style="border-top: 1px solid #e0e0e0;">
|
|
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>{{ t('ui.change_password.back_to_home') }}
|
|
57
|
+
</a>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
44
64
|
</div>
|
|
65
|
+
|
|
45
66
|
{% endblock %}
|
iatoolkit/templates/chat.html
CHANGED
|
@@ -1,67 +1,101 @@
|
|
|
1
1
|
{% extends "base.html" %}
|
|
2
2
|
|
|
3
|
-
{% block title %}
|
|
3
|
+
{% block title %}{{ branding.name }} IA{% endblock %}
|
|
4
4
|
|
|
5
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">
|
|
6
14
|
|
|
7
|
-
|
|
8
|
-
{{ branding.css_variables | safe }}
|
|
9
|
-
</style>
|
|
15
|
+
{% endblock %}
|
|
10
16
|
|
|
11
17
|
<!-- Sección de encabezado con el usuario conectado -->
|
|
12
|
-
<div id="company-section"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<!-- Izquierda: Nombre de la Empresa y atribución "Powered by" -->
|
|
16
|
-
<div class="d-flex align-items-center">
|
|
17
|
-
<span style="{{ branding.primary_text_style }}">
|
|
18
|
-
{{ branding.name }}
|
|
19
|
-
</span>
|
|
20
|
-
<span class="ms-2" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Powered by IAToolkit">
|
|
21
|
-
<i class="bi bi-info-circle" style="color: {{ branding.header_text_color }}; opacity: 0.7; font-size: 0.9rem;"></i>
|
|
22
|
-
</span>
|
|
23
|
-
</div>
|
|
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 }}">
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<!-- 3. Iconos de Acción -->
|
|
36
|
-
<a href="javascript:void(0);" id="history-button"
|
|
37
|
-
class="action-icon-style" title="Historial con mis consultas" style="color: {{ branding.header_text_color }};">
|
|
38
|
-
<i class="bi bi-clock-history"></i>
|
|
39
|
-
</a>
|
|
40
|
-
<a href="javascript:void(0);" id="send-feedback-button"
|
|
41
|
-
class="ms-3 action-icon-style" title="Tu feedback es muy importante" style="color: {{ branding.header_text_color }};">
|
|
42
|
-
<i class="bi bi-emoji-smile"></i>
|
|
43
|
-
</a>
|
|
44
|
-
|
|
45
|
-
<!-- Icono de cerrar sesión (al final) -->
|
|
46
|
-
{% if user.email %}
|
|
47
|
-
<a href="{{ url_for('logout', company_short_name=company_short_name) }}"
|
|
48
|
-
class="ms-3 action-icon-style" title="Cerrar sesión" style="color: {{ branding.header_text_color }} !important;">
|
|
49
|
-
<i class="bi bi-box-arrow-right"></i>
|
|
50
|
-
</a>
|
|
51
|
-
{% endif %}
|
|
52
|
-
</div>
|
|
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 ({{ 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
|
+
</div>
|
|
53
32
|
|
|
54
|
-
|
|
33
|
+
<!-- Contenedor para la derecha que agrupa ID de usuario y botones -->
|
|
34
|
+
<div class="d-flex flex-column flex-md-row align-items-center">
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
36
|
+
<!-- Fila 2 (Móvil) / Parte 1 de la Columna Derecha (Desktop): ID de Usuario -->
|
|
37
|
+
<span style="{{ branding.secondary_text_style }}" class="mb-2 mb-md-0">
|
|
38
|
+
{{ user_identifier }}
|
|
39
|
+
</span>
|
|
40
|
+
|
|
41
|
+
<!-- Separador Vertical (Solo visible en Desktop) -->
|
|
42
|
+
<div class="vr mx-3 d-none d-md-block"></div>
|
|
43
|
+
|
|
44
|
+
<!-- Fila 3 (Móvil) / Parte 2 de la Columna Derecha (Desktop): Iconos de Acción -->
|
|
45
|
+
<div class="d-flex align-items-center">
|
|
46
|
+
<a href="javascript:void(0);"
|
|
47
|
+
id="history-button"
|
|
48
|
+
class="action-icon-style" title="{{ t('ui.tooltips.history') }}"
|
|
49
|
+
style="color: {{ branding.header_text_color }};">
|
|
50
|
+
<i class="bi bi-clock-history"></i>
|
|
51
|
+
</a>
|
|
52
|
+
<a href="javascript:void(0);"
|
|
53
|
+
id="force-reload-button"
|
|
54
|
+
class="ms-3 action-icon-style"
|
|
55
|
+
title="{{ t('ui.tooltips.reload_context') }}"
|
|
56
|
+
style="color: {{ branding.header_text_color }};">
|
|
57
|
+
<i class="bi bi-arrow-clockwise"></i>
|
|
58
|
+
</a>
|
|
59
|
+
<a href="javascript:void(0);"
|
|
60
|
+
id="send-feedback-button"
|
|
61
|
+
class="ms-3 action-icon-style"
|
|
62
|
+
title="{{ t('ui.tooltips.feedback') }}"
|
|
63
|
+
style="color: {{ branding.header_text_color }};">
|
|
64
|
+
<i class="bi bi-emoji-smile"></i>
|
|
65
|
+
</a>
|
|
66
|
+
|
|
67
|
+
<a href="javascript:void(0);"
|
|
68
|
+
id="onboarding-button"
|
|
69
|
+
class="ms-3 action-icon-style"
|
|
70
|
+
title="{{ t('ui.tooltips.onboarding') }}"
|
|
71
|
+
style="color: {{ branding.header_text_color }};">
|
|
72
|
+
<i class="bi bi-lightbulb"></i>
|
|
73
|
+
</a>
|
|
74
|
+
<a href="javascript:void(0);"
|
|
75
|
+
id="open-help-button"
|
|
76
|
+
class="ms-3 action-icon-style"
|
|
77
|
+
title="{{ t('ui.tooltips.usage_guide') }}"
|
|
78
|
+
style="color: {{ branding.header_text_color }};">
|
|
79
|
+
<i class="bi bi-question-circle-fill"></i>
|
|
80
|
+
</a>
|
|
81
|
+
<a href="javascript:void(0);"
|
|
82
|
+
id="logout-button"
|
|
83
|
+
class="ms-3 action-icon-style"
|
|
84
|
+
title="{{ t('ui.tooltips.logout') }}"
|
|
85
|
+
style="color: {{ branding.header_text_color }}; !important;">
|
|
86
|
+
<i class="bi bi-box-arrow-right"></i>
|
|
87
|
+
</a>
|
|
88
|
+
</div>
|
|
63
89
|
</div>
|
|
64
90
|
</div>
|
|
91
|
+
|
|
92
|
+
<div id="chat-container"
|
|
93
|
+
class="chat-block mt-2 flex-grow-1" style="overflow-y: auto;">
|
|
94
|
+
|
|
95
|
+
<!-- Mensaje de bienvenida -->
|
|
96
|
+
<div class="answer-section">
|
|
97
|
+
{{ t('ui.chat.welcome_message') }}
|
|
98
|
+
</div>
|
|
65
99
|
</div>
|
|
66
100
|
|
|
67
101
|
<!-- Input oculto de FilePond -->
|
|
@@ -79,8 +113,11 @@
|
|
|
79
113
|
<div class="{{ prompt_col_class }}">
|
|
80
114
|
<div class="position-relative h-100">
|
|
81
115
|
<div class="input-group dropup h-100">
|
|
82
|
-
<button type="button" id="prompt-select-button"
|
|
83
|
-
|
|
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">
|
|
120
|
+
{{ t('ui.chat.prompts_available') }} ....
|
|
84
121
|
</button>
|
|
85
122
|
<ul class="dropdown-menu dropdown-menu-soft w-100">
|
|
86
123
|
{% if prompts and prompts.message %}
|
|
@@ -94,13 +131,20 @@
|
|
|
94
131
|
data-custom-fields='{{ prompt.custom_fields | tojson }}'>
|
|
95
132
|
{{ prompt.description }}
|
|
96
133
|
</a>
|
|
97
|
-
</li>
|
|
98
|
-
{%
|
|
134
|
+
</li>
|
|
135
|
+
{% endfor %}
|
|
136
|
+
{% if not loop.last %}
|
|
137
|
+
<li><hr class="dropdown-divider"></li>
|
|
138
|
+
{% endif %}
|
|
99
139
|
{% endfor %}
|
|
100
140
|
{% endif %}
|
|
101
141
|
</ul>
|
|
102
142
|
</div>
|
|
103
|
-
<button type="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>
|
|
104
148
|
</div>
|
|
105
149
|
<input type="hidden" id="prompt-select-value" name="prompt_select_value">
|
|
106
150
|
<input type="hidden" id="prompt-select-description" name="prompt-select-description">
|
|
@@ -117,34 +161,41 @@
|
|
|
117
161
|
<div id="chat-input-bar" class="chat-input-bar d-flex align-items-center">
|
|
118
162
|
<!-- Iconos de la izquierda -->
|
|
119
163
|
<div class="d-flex align-items-center">
|
|
120
|
-
<!--
|
|
121
|
-
<a class="p-2" href="#prompt-assistant-collapse" data-bs-toggle="collapse" role="button"
|
|
164
|
+
<!-- varita magica -->
|
|
165
|
+
<a class="p-2" href="#prompt-assistant-collapse" data-bs-toggle="collapse" role="button"
|
|
166
|
+
aria-expanded="false" aria-controls="prompt-assistant-collapse"
|
|
167
|
+
title="{{ t('ui.tooltips.use_prompt_assistant') }}">
|
|
122
168
|
<i class="bi bi-magic"></i>
|
|
123
169
|
</a>
|
|
124
|
-
<a class="p-2" href="javascript:void(0);" id="paperclip-button"
|
|
170
|
+
<a class="p-2" href="javascript:void(0);" id="paperclip-button"
|
|
171
|
+
title="{{ t('ui.tooltips.attach_files') }}">
|
|
125
172
|
<i class="bi bi-plus-circle"></i>
|
|
126
173
|
</a>
|
|
127
174
|
<div id="view-files-button-container" style="display: none;">
|
|
128
|
-
<a class="p-2" href="javascript:void(0);" id="view-files-button"
|
|
175
|
+
<a class="p-2" href="javascript:void(0);" id="view-files-button"
|
|
176
|
+
title="{{ t('ui.tooltips.view_attached_files') }}">
|
|
129
177
|
<i class="bi bi-file-earmark-text"></i>
|
|
130
178
|
</a>
|
|
131
179
|
</div>
|
|
132
180
|
</div>
|
|
133
181
|
|
|
134
182
|
<!-- Textarea Central -->
|
|
135
|
-
<textarea id="question" placeholder="
|
|
183
|
+
<textarea id="question" placeholder="{{ t('ui.chat.input_placeholder') }}"
|
|
184
|
+
class="form-control chat-textarea" style="resize: none;" rows="1"></textarea>
|
|
136
185
|
|
|
137
186
|
<!-- Botón de Enviar a la derecha -->
|
|
138
187
|
<div class="d-flex align-items-center">
|
|
139
188
|
<div id="send-button-container">
|
|
140
189
|
<a href="javascript:void(0);" id="send-button"
|
|
141
|
-
class="p-2 send-button-icon"
|
|
190
|
+
class="p-2 send-button-icon"
|
|
191
|
+
title="{{ t('ui.buttons.send') }}">
|
|
142
192
|
<i class="bi bi-arrow-up-circle-fill"></i>
|
|
143
193
|
</a>
|
|
144
194
|
</div>
|
|
145
195
|
<div id="stop-button-container" style="display: none;">
|
|
146
196
|
<a href="javascript:void(0);" id="stop-button"
|
|
147
|
-
class="p-2 text-danger"
|
|
197
|
+
class="p-2 text-danger"
|
|
198
|
+
title="{{ t('ui.buttons.stop') }}">
|
|
148
199
|
<i class="bi bi-stop-circle-fill"></i>
|
|
149
200
|
</a>
|
|
150
201
|
</div>
|
|
@@ -155,41 +206,44 @@
|
|
|
155
206
|
<!-- Incluir los modales desde un archivo externo -->
|
|
156
207
|
{% include 'chat_modals.html' %}
|
|
157
208
|
|
|
209
|
+
</div>
|
|
158
210
|
{% endblock %}
|
|
159
211
|
|
|
160
212
|
{% block scripts %}
|
|
161
213
|
<script>
|
|
162
214
|
// --- Global Configuration from Backend ---
|
|
163
215
|
window.companyShortName = "{{ company_short_name }}";
|
|
216
|
+
window.user_identifier = "{{ user_identifier }}";
|
|
217
|
+
window.redeemToken = {{ redeem_token | tojson | default('null') }};
|
|
164
218
|
window.iatoolkit_base_url = "{{ iatoolkit_base_url }}";
|
|
165
|
-
window.externalUserId = "{{ external_user_id }}";
|
|
166
219
|
window.availablePrompts = {{ prompts.message | tojson }};
|
|
220
|
+
window.onboardingCards = {{ onboarding_cards | tojson }};
|
|
221
|
+
window.sendButtonColor = "{{ branding.send_button_color }}";
|
|
222
|
+
|
|
223
|
+
// JS translations helper
|
|
224
|
+
window.i18n = {{ js_translations | tojson }};
|
|
225
|
+
function t_js(key) {
|
|
226
|
+
return window.i18n[key] || key;
|
|
227
|
+
}
|
|
228
|
+
|
|
167
229
|
|
|
168
|
-
{% if auth_method == 'jwt' and session_jwt %}
|
|
169
|
-
// Store session JWT if it exists, defined in the same global scope
|
|
170
|
-
window.sessionJWT = "{{ session_jwt }}";
|
|
171
|
-
{% endif %}
|
|
172
230
|
</script>
|
|
173
231
|
|
|
174
232
|
<!-- Carga de los scripts JS externos después de definir las variables globales -->
|
|
175
|
-
<script src="{{ url_for('static', filename='js/
|
|
176
|
-
<script src="{{ url_for('static', filename='js/
|
|
177
|
-
<script src="{{ url_for('static', filename='js/
|
|
178
|
-
<script src="{{ url_for('static', filename='js/
|
|
233
|
+
<script src="{{ url_for('static', filename='js/chat_history_button.js', _external=True) }}"></script>
|
|
234
|
+
<script src="{{ url_for('static', filename='js/chat_reload_button.js', _external=True) }}"></script>
|
|
235
|
+
<script src="{{ url_for('static', filename='js/chat_feedback_button.js', _external=True) }}"></script>
|
|
236
|
+
<script src="{{ url_for('static', filename='js/chat_help_content.js', _external=True) }}"></script>
|
|
237
|
+
<script src="{{ url_for('static', filename='js/chat_onboarding_button.js', _external=True) }}"></script>
|
|
238
|
+
<script src="{{ url_for('static', filename='js/chat_logout_button.js', _external=True) }}"></script>
|
|
239
|
+
<script src="{{ url_for('static', filename='js/chat_prompt_manager.js', _external=True) }}"></script>
|
|
240
|
+
<script src="{{ url_for('static', filename='js/chat_filepond.js', _external=True) }}"></script>
|
|
241
|
+
<script src="{{ url_for('static', filename='js/chat_main.js', _external=True) }}"></script>
|
|
242
|
+
|
|
243
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
|
244
|
+
|
|
245
|
+
<script>
|
|
179
246
|
|
|
180
|
-
<script>
|
|
181
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
182
|
-
const promptCollapse = document.getElementById('prompt-assistant-collapse');
|
|
183
|
-
if (promptCollapse) {
|
|
184
|
-
promptCollapse.addEventListener('shown.bs.collapse', function () {
|
|
185
|
-
// Desplazar la ventana al final de la página para mantener visible el área de entrada.
|
|
186
|
-
window.scrollTo({
|
|
187
|
-
top: document.body.scrollHeight,
|
|
188
|
-
behavior: 'smooth'
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
247
|
document.addEventListener('DOMContentLoaded', function () {
|
|
194
248
|
// Inicializar todos los tooltips de la página
|
|
195
249
|
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
|
@@ -197,5 +251,45 @@
|
|
|
197
251
|
return new bootstrap.Tooltip(tooltipTriggerEl)
|
|
198
252
|
})
|
|
199
253
|
});
|
|
254
|
+
|
|
255
|
+
// Inicialización del modal de onboarding
|
|
256
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
257
|
+
const btn = document.getElementById('onboarding-button');
|
|
258
|
+
if (!btn) return;
|
|
259
|
+
|
|
260
|
+
const modalEl = document.getElementById('onboardingModal');
|
|
261
|
+
const modal = new bootstrap.Modal(modalEl);
|
|
262
|
+
|
|
263
|
+
if (!window.initOnboarding) {
|
|
264
|
+
console.error('initOnboarding no disponible. Verifica chat_onboarding.js');
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const onboarding = initOnboarding({
|
|
269
|
+
mode: 'modal',
|
|
270
|
+
cards: Array.isArray(window.onboardingCards) ? window.onboardingCards : [],
|
|
271
|
+
ui: {
|
|
272
|
+
icon: '#ob-icon',
|
|
273
|
+
title: '#ob-title',
|
|
274
|
+
text: '#ob-text',
|
|
275
|
+
example: '#ob-example',
|
|
276
|
+
dots: '#ob-dots',
|
|
277
|
+
prev: '#ob-prev',
|
|
278
|
+
next: '#ob-next'
|
|
279
|
+
},
|
|
280
|
+
autoRotateMs: 5000
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
modalEl.addEventListener('hidden.bs.modal', () => onboarding.stop());
|
|
284
|
+
|
|
285
|
+
btn.addEventListener('click', () => {
|
|
286
|
+
if (!onboarding.hasCards()) {
|
|
287
|
+
toastr.info('No hay información de onboarding disponible.');
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
onboarding.start();
|
|
291
|
+
modal.show();
|
|
292
|
+
});
|
|
293
|
+
});
|
|
200
294
|
</script>
|
|
201
295
|
{% endblock %}
|