iatoolkit 0.18.1__tar.gz → 0.20.0__tar.gz
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-0.18.1 → iatoolkit-0.20.0}/PKG-INFO +1 -1
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/pyproject.toml +1 -1
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/common/routes.py +18 -7
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/iatoolkit.py +4 -1
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/branding_service.py +10 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/js/chat_history.js +5 -7
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/js/chat_main.js +1 -1
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +5 -0
- iatoolkit-0.20.0/src/iatoolkit/static/styles/landing_page.css +156 -0
- iatoolkit-0.20.0/src/iatoolkit/templates/_branding_styles.html +53 -0
- iatoolkit-0.20.0/src/iatoolkit/templates/_login_widget.html +42 -0
- iatoolkit-0.20.0/src/iatoolkit/templates/_navbar.html +9 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/base.html +2 -0
- iatoolkit-0.20.0/src/iatoolkit/templates/change_password.html +64 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/chat.html +3 -2
- iatoolkit-0.20.0/src/iatoolkit/templates/forgot_password.html +48 -0
- iatoolkit-0.20.0/src/iatoolkit/templates/index.html +126 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/onboarding_shell.html +1 -1
- iatoolkit-0.20.0/src/iatoolkit/templates/signup.html +74 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/change_password_view.py +17 -8
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/forgot_password_view.py +15 -9
- iatoolkit-0.20.0/src/iatoolkit/views/index_view.py +43 -0
- iatoolkit-0.20.0/src/iatoolkit/views/init_context_view.py +35 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/login_view.py +1 -1
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/signup_view.py +30 -25
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/verify_user_view.py +6 -6
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit.egg-info/PKG-INFO +1 -1
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit.egg-info/SOURCES.txt +7 -0
- iatoolkit-0.18.1/src/iatoolkit/templates/change_password.html +0 -45
- iatoolkit-0.18.1/src/iatoolkit/templates/forgot_password.html +0 -33
- iatoolkit-0.18.1/src/iatoolkit/templates/signup.html +0 -78
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/readme.md +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/requirements.txt +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/setup.cfg +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/common/auth.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/gemini_adapter.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/llm_client.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/mail_app.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/openai_adapter.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/models.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/tasks_repo.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/benchmark_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/document_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/history_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/load_documents_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/onboarding_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/prompt_manager_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/query_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/search_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/tasks_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/arrow_up.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/logo_clinica.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/logo_iatoolkit.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/logo_maxxa.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/logo_notaria.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/logo_tarjeta.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/logo_umayor.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/images/upload.png +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/js/chat_feedback.js +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/styles/chat_info.css +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/about.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/header.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/home.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/login.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/templates/test.html +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/chat_token_request_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/download_file_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/external_login_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/file_store_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/history_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/llmquery_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/prompt_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/tasks_review_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/tasks_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit/views/user_feedback_view.py +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-0.18.1 → iatoolkit-0.20.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -13,15 +13,14 @@ import os
|
|
|
13
13
|
def logout(company_short_name: str):
|
|
14
14
|
SessionManager.clear()
|
|
15
15
|
flash("Has cerrado sesión correctamente", "info")
|
|
16
|
-
|
|
17
|
-
return redirect(url_for('login', company_short_name=company_short_name))
|
|
18
|
-
else:
|
|
19
|
-
return redirect(url_for('home'))
|
|
16
|
+
return redirect(url_for('index', company_short_name=company_short_name))
|
|
20
17
|
|
|
21
18
|
|
|
22
19
|
# this function register all the views
|
|
23
20
|
def register_views(injector, app):
|
|
24
21
|
|
|
22
|
+
from iatoolkit.views.index_view import IndexView
|
|
23
|
+
from iatoolkit.views.init_context_view import InitContextView
|
|
25
24
|
from iatoolkit.views.llmquery_view import LLMQueryView
|
|
26
25
|
from iatoolkit.views.tasks_view import TaskView
|
|
27
26
|
from iatoolkit.views.tasks_review_view import TaskReviewView
|
|
@@ -38,11 +37,14 @@ def register_views(injector, app):
|
|
|
38
37
|
from iatoolkit.views.chat_token_request_view import ChatTokenRequestView
|
|
39
38
|
from iatoolkit.views.download_file_view import DownloadFileView
|
|
40
39
|
|
|
41
|
-
|
|
40
|
+
# landing page
|
|
41
|
+
app.add_url_rule('/<company_short_name>', view_func=IndexView.as_view('index'))
|
|
42
|
+
app.add_url_rule('/<company_short_name>/initiate_external_chat',
|
|
43
|
+
view_func=InitContextView.as_view('initiate_external_chat'))
|
|
42
44
|
|
|
43
45
|
# login for external portals
|
|
44
|
-
app.add_url_rule('/<company_short_name>/
|
|
45
|
-
view_func=
|
|
46
|
+
app.add_url_rule('/<company_short_name>/<external_user_id>/init-context',
|
|
47
|
+
view_func=InitContextView.as_view('init-context'))
|
|
46
48
|
app.add_url_rule('/<company_short_name>/external_login',
|
|
47
49
|
view_func=ExternalChatLoginView.as_view('external_login'))
|
|
48
50
|
app.add_url_rule('/auth/chat_token',
|
|
@@ -68,6 +70,9 @@ def register_views(injector, app):
|
|
|
68
70
|
app.add_url_rule('/tasks/review/<int:task_id>', view_func=TaskReviewView.as_view('tasks-review'))
|
|
69
71
|
app.add_url_rule('/load', view_func=FileStoreView.as_view('load'))
|
|
70
72
|
|
|
73
|
+
# login testing /login_testing
|
|
74
|
+
app.add_url_rule('/login_testing', view_func=HomeView.as_view('home'))
|
|
75
|
+
|
|
71
76
|
app.add_url_rule(
|
|
72
77
|
'/about', # URL de la ruta
|
|
73
78
|
view_func=lambda: render_template('about.html'))
|
|
@@ -99,3 +104,9 @@ def register_views(injector, app):
|
|
|
99
104
|
except FileNotFoundError:
|
|
100
105
|
abort(404)
|
|
101
106
|
|
|
107
|
+
# Redirección opcional: hacer que la raíz '/' vaya a la landing de sample_company
|
|
108
|
+
@app.route('/')
|
|
109
|
+
def root_redirect():
|
|
110
|
+
return redirect(url_for('index', company_short_name='sample_company'))
|
|
111
|
+
|
|
112
|
+
|
|
@@ -153,7 +153,6 @@ class IAToolkit:
|
|
|
153
153
|
except PackageNotFoundError:
|
|
154
154
|
pass
|
|
155
155
|
|
|
156
|
-
self.app.wsgi_app = ProxyFix(self.app.wsgi_app, x_proto=1)
|
|
157
156
|
|
|
158
157
|
self.app.config.update({
|
|
159
158
|
'VERSION': self.version,
|
|
@@ -171,6 +170,9 @@ class IAToolkit:
|
|
|
171
170
|
if parsed_url.scheme == 'https':
|
|
172
171
|
self.app.config['PREFERRED_URL_SCHEME'] = 'https'
|
|
173
172
|
|
|
173
|
+
# 2. ProxyFix para no tener problemas con iframes y rutas
|
|
174
|
+
self.app.wsgi_app = ProxyFix(self.app.wsgi_app, x_proto=1)
|
|
175
|
+
|
|
174
176
|
# Configuración para tokenizers en desarrollo
|
|
175
177
|
if is_dev:
|
|
176
178
|
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
|
@@ -379,6 +381,7 @@ class IAToolkit:
|
|
|
379
381
|
'app_name': 'IAToolkit',
|
|
380
382
|
'user': SessionManager.get('user'),
|
|
381
383
|
'user_company': SessionManager.get('company_short_name'),
|
|
384
|
+
'iatoolkit_base_url': os.environ.get('IATOOLKIT_BASE_URL', ''),
|
|
382
385
|
}
|
|
383
386
|
|
|
384
387
|
def _get_default_static_folder(self) -> str:
|
|
@@ -71,6 +71,14 @@ class BrandingService:
|
|
|
71
71
|
if company and company.branding:
|
|
72
72
|
final_branding_values.update(company.branding)
|
|
73
73
|
|
|
74
|
+
# Función para convertir HEX a RGB
|
|
75
|
+
def hex_to_rgb(hex_color):
|
|
76
|
+
hex_color = hex_color.lstrip('#')
|
|
77
|
+
return tuple(int(hex_color[i:i + 2], 16) for i in (0, 2, 4))
|
|
78
|
+
|
|
79
|
+
primary_rgb = hex_to_rgb(final_branding_values['brand_primary_color'])
|
|
80
|
+
secondary_rgb = hex_to_rgb(final_branding_values['brand_secondary_color'])
|
|
81
|
+
|
|
74
82
|
# --- CONSTRUCCIÓN DE ESTILOS Y VARIABLES CSS ---
|
|
75
83
|
header_style = (
|
|
76
84
|
f"background-color: {final_branding_values['header_background_color']}; "
|
|
@@ -95,6 +103,8 @@ class BrandingService:
|
|
|
95
103
|
:root {{
|
|
96
104
|
--brand-primary-color: {final_branding_values['brand_primary_color']};
|
|
97
105
|
--brand-secondary-color: {final_branding_values['brand_secondary_color']};
|
|
106
|
+
--brand-primary-color-rgb: {', '.join(map(str, primary_rgb))};
|
|
107
|
+
--brand-secondary-color-rgb: {', '.join(map(str, secondary_rgb))};
|
|
98
108
|
--brand-text-on-primary: {final_branding_values['brand_text_on_primary']};
|
|
99
109
|
--brand-text-on-secondary: {final_branding_values['brand_text_on_secondary']};
|
|
100
110
|
--brand-modal-header-bg: {final_branding_values['header_background_color']};
|
|
@@ -12,7 +12,7 @@ $(document).ready(function () {
|
|
|
12
12
|
const queryText = $(this).data('query');
|
|
13
13
|
|
|
14
14
|
// Copiar el texto al textarea del chat
|
|
15
|
-
if (queryText) {
|
|
15
|
+
if (queryText) {
|
|
16
16
|
$('#question').val(queryText);
|
|
17
17
|
autoResizeTextarea($('#question')[0]);
|
|
18
18
|
$('#send-button').removeClass('disabled');
|
|
@@ -92,7 +92,7 @@ $(document).ready(function () {
|
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
// Poblar tabla
|
|
95
|
+
// Poblar la tabla
|
|
96
96
|
filteredHistory.forEach((item, index) => {
|
|
97
97
|
const icon = $('<i>').addClass('bi bi-pencil-fill');
|
|
98
98
|
|
|
@@ -100,23 +100,21 @@ $(document).ready(function () {
|
|
|
100
100
|
.attr('href', 'javascript:void(0);')
|
|
101
101
|
.addClass('copy-query-icon')
|
|
102
102
|
.attr('title', 'Copiar consulta al chat')
|
|
103
|
-
.data('query', item.query)
|
|
103
|
+
.data('query', item.query)
|
|
104
104
|
.append(icon);
|
|
105
105
|
|
|
106
106
|
const row = $('<tr>').append(
|
|
107
107
|
$('<td>').text(index + 1),
|
|
108
108
|
$('<td>').addClass('date-cell').text(formatDate(item.created_at)),
|
|
109
|
-
$('<td>').text(item.query),
|
|
109
|
+
$('<td>').text(item.query),
|
|
110
110
|
$('<td>').addClass('text-center').append(link)
|
|
111
111
|
);
|
|
112
112
|
|
|
113
113
|
historyTableBody.append(row);
|
|
114
114
|
});
|
|
115
|
-
|
|
116
|
-
// El event handler ya no se adjunta aquí.
|
|
117
115
|
}
|
|
118
116
|
|
|
119
|
-
// Función para formatear fecha
|
|
117
|
+
// Función para formatear fecha
|
|
120
118
|
function formatDate(dateString) {
|
|
121
119
|
const date = new Date(dateString);
|
|
122
120
|
|
|
@@ -403,7 +403,7 @@ const showSpinner = function () {
|
|
|
403
403
|
<div class="spinner-border text-primary" role="status" style="width: 1.5rem; height: 1.5rem; margin-right: 15px;">
|
|
404
404
|
<span class="${accessibilityClass}">Loading...</span>
|
|
405
405
|
</div>
|
|
406
|
-
<span style="font-weight: bold; font-size: 15px;">
|
|
406
|
+
<span style="font-weight: bold; font-size: 15px;">Cargando...</span>
|
|
407
407
|
</div>
|
|
408
408
|
`);
|
|
409
409
|
$('#chat-container').append(spinner).scrollTop($('#chat-container')[0].scrollHeight);
|
|
@@ -185,6 +185,11 @@
|
|
|
185
185
|
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
/* Aplica el color secundario de la marca al icono de ver archivos */
|
|
189
|
+
#view-files-button i {
|
|
190
|
+
color: var(--brand-secondary-color, #6c757d);
|
|
191
|
+
}
|
|
192
|
+
|
|
188
193
|
/* Estilo para mensajes sutiles del sistema (ej. abortado) */
|
|
189
194
|
.system-message {
|
|
190
195
|
color: var(--brand-secondary-color, #6c757d); /* Usa el color secundario o un gris por defecto */
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/* static/styles/landing_page.css */
|
|
2
|
+
|
|
3
|
+
/* --- Configuración General --- */
|
|
4
|
+
body {
|
|
5
|
+
background-color: #ffffff; /* Cambiado a blanco para que el hero destaque */
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* --- 1. Barra de Navegación Superior --- */
|
|
9
|
+
.landing-navbar {
|
|
10
|
+
background-color: var(--brand-primary-color, #0d6efd);
|
|
11
|
+
padding: 1rem 1.5rem;
|
|
12
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.landing-navbar .navbar-brand {
|
|
16
|
+
color: var(--brand-text-on-primary, #FFFFFF);
|
|
17
|
+
font-weight: 700;
|
|
18
|
+
font-size: 1.8rem; /* Aumentado el tamaño del texto */
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* --- 2. Sección Principal (Hero) --- */
|
|
22
|
+
.hero-section {
|
|
23
|
+
padding: 5rem 0; /* <-- ESTA LÍNEA RESTAURA EL ESPACIADO SUPERIOR E INFERIOR */
|
|
24
|
+
background-color: #f8f9fa; /* Fondo gris claro para la sección principal */
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Estilos para el texto de la propuesta de valor */
|
|
28
|
+
.value-proposition {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
height: 100%;
|
|
33
|
+
/* Se ajusta el padding para la nueva posición a la izquierda */
|
|
34
|
+
padding-left: 2rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.value-proposition .hero-title {
|
|
38
|
+
font-size: 2.8rem;
|
|
39
|
+
font-weight: 700;
|
|
40
|
+
line-height: 1.2;
|
|
41
|
+
color: #212529;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.value-proposition .hero-accelerator {
|
|
45
|
+
color: var(--brand-primary-color, #0d6efd);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.value-proposition .hero-subtitle {
|
|
49
|
+
font-size: 1.1rem;
|
|
50
|
+
color: #6c757d;
|
|
51
|
+
margin-top: 1.5rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* --- Estilo para el título del widget de login --- */
|
|
55
|
+
.hero-section .bg-light h4 {
|
|
56
|
+
color: var(--brand-primary-color, #0d6efd);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* --- Estilo para el texto introductorio del widget --- */
|
|
60
|
+
.widget-intro-text {
|
|
61
|
+
font-style: italic;
|
|
62
|
+
font-size: 0.9rem;
|
|
63
|
+
line-height: 1.4;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/* --- 3. Sección de Características --- */
|
|
68
|
+
.features-section {
|
|
69
|
+
padding: 5rem 0;
|
|
70
|
+
background-color: #ffffff; /* Fondo blanco para esta sección */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* (El resto del archivo CSS permanece sin cambios) */
|
|
74
|
+
.feature-item {
|
|
75
|
+
text-align: center;
|
|
76
|
+
padding: 2rem;
|
|
77
|
+
background-color: #f8f9fa; /* Fondo gris claro para cada tarjeta */
|
|
78
|
+
border: 1px solid #dee2e6;
|
|
79
|
+
border-radius: 0.5rem;
|
|
80
|
+
height: 100%; /* CLAVE: Asegura que todas las tarjetas en una fila tengan el mismo alto */
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.feature-icon {
|
|
84
|
+
font-size: 3rem;
|
|
85
|
+
color: var(--brand-primary-color); /* Usar color primario para más impacto */
|
|
86
|
+
margin-bottom: 1.5rem;
|
|
87
|
+
display: inline-block;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.feature-item h3 {
|
|
91
|
+
font-size: 1.4rem;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
margin-bottom: 1rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.feature-item p {
|
|
97
|
+
color: #6c757d;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.opensource-box {
|
|
101
|
+
background-color: #343a40;
|
|
102
|
+
color: #f8f9fa;
|
|
103
|
+
padding: 2rem;
|
|
104
|
+
border-radius: 0.5rem;
|
|
105
|
+
height: 100%; /* CLAVE: Asegura que tenga el mismo alto */
|
|
106
|
+
display: flex;
|
|
107
|
+
flex-direction: column;
|
|
108
|
+
justify-content: space-between;
|
|
109
|
+
text-align: center;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.opensource-icon {
|
|
113
|
+
font-size: 3rem; /* Tamaño consistente con los otros iconos */
|
|
114
|
+
color: var(--brand-text-on-primary, #FFFFFF);
|
|
115
|
+
opacity: 0.9;
|
|
116
|
+
margin-bottom: 1.5rem;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.opensource-content h3 {
|
|
120
|
+
font-weight: 600;
|
|
121
|
+
font-size: 1.4rem; /* Tamaño consistente */
|
|
122
|
+
margin-bottom: 1rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.opensource-content p {
|
|
126
|
+
margin-bottom: 1.5rem;
|
|
127
|
+
color: #adb5bd;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.opensource-content .btn {
|
|
131
|
+
width: 100%;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.pypi-link {
|
|
135
|
+
margin-top: 1.5rem;
|
|
136
|
+
padding-top: 1.5rem;
|
|
137
|
+
border-top: 1px solid #495057;
|
|
138
|
+
font-size: 0.9rem;
|
|
139
|
+
color: #ced4da;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.pypi-link code {
|
|
143
|
+
background-color: #212529;
|
|
144
|
+
padding: 0.2rem 0.5rem;
|
|
145
|
+
border-radius: 4px;
|
|
146
|
+
color: #e83e8c;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* --- 4. Footer --- */
|
|
150
|
+
.landing-footer {
|
|
151
|
+
background-color: #343a40;
|
|
152
|
+
color: #adb5bd;
|
|
153
|
+
padding: 2rem 0;
|
|
154
|
+
text-align: center;
|
|
155
|
+
font-size: 0.9rem;
|
|
156
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<!-- templates/_branding_styles.html -->
|
|
2
|
+
<style>
|
|
3
|
+
{{ branding.css_variables | safe }}
|
|
4
|
+
|
|
5
|
+
/* Clases de botón reutilizables basadas en el branding */
|
|
6
|
+
.btn-branded-primary {
|
|
7
|
+
background-color: var(--brand-primary-color);
|
|
8
|
+
color: var(--brand-text-on-primary);
|
|
9
|
+
border-color: var(--brand-primary-color);
|
|
10
|
+
transition: all 0.2s ease-in-out;
|
|
11
|
+
}
|
|
12
|
+
.btn-branded-primary:hover {
|
|
13
|
+
color: var(--brand-text-on-primary);
|
|
14
|
+
box-shadow: inset 0 0 0 200px rgba(0, 0, 0, 0.15);
|
|
15
|
+
}
|
|
16
|
+
.btn-branded-secondary {
|
|
17
|
+
background-color: var(--brand-secondary-color);
|
|
18
|
+
color: var(--brand-text-on-secondary);
|
|
19
|
+
border-color: var(--brand-secondary-color);
|
|
20
|
+
transition: all 0.2s ease-in-out;
|
|
21
|
+
}
|
|
22
|
+
.btn-branded-secondary:hover {
|
|
23
|
+
color: var(--brand-text-on-secondary);
|
|
24
|
+
box-shadow: inset 0 0 0 200px rgba(0, 0, 0, 0.15);
|
|
25
|
+
}
|
|
26
|
+
.form-title {
|
|
27
|
+
color: var(--brand-primary-color);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* --- ESTILOS CORREGIDOS Y MÁS ESPECÍFICOS PARA SWEETALERT2 --- */
|
|
31
|
+
|
|
32
|
+
/* Botón de Confirmar (OK) */
|
|
33
|
+
.swal2-confirm.custom-confirm-button {
|
|
34
|
+
background-color: var(--brand-primary-color) !important;
|
|
35
|
+
color: var(--brand-text-on-primary) !important;
|
|
36
|
+
border: 1px solid var(--brand-primary-color) !important;
|
|
37
|
+
box-shadow: none !important;
|
|
38
|
+
}
|
|
39
|
+
.swal2-confirm.custom-confirm-button:hover {
|
|
40
|
+
box-shadow: inset 0 0 0 200px rgba(0, 0, 0, 0.15) !important;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Botón de Cancelar */
|
|
44
|
+
.swal2-cancel.custom-cancel-button {
|
|
45
|
+
background-color: var(--brand-secondary-color) !important;
|
|
46
|
+
color: var(--brand-text-on-secondary) !important;
|
|
47
|
+
border: 1px solid var(--brand-secondary-color) !important;
|
|
48
|
+
box-shadow: none !important;
|
|
49
|
+
}
|
|
50
|
+
.swal2-cancel.custom-cancel-button:hover {
|
|
51
|
+
box-shadow: inset 0 0 0 200px rgba(0, 0, 0, 0.15) !important;
|
|
52
|
+
}
|
|
53
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!-- templates/_login_widget.html -->
|
|
2
|
+
<div class="border rounded p-4 shadow-sm bg-light">
|
|
3
|
+
<!-- 1. Nuevo Encabezado de Marketing -->
|
|
4
|
+
<div class="text-center mb-4">
|
|
5
|
+
<h4 class="form-title fw-bold">Acceso a la Plataforma</h4>
|
|
6
|
+
<!-- Párrafo modificado con nuevo texto y nueva clase CSS -->
|
|
7
|
+
<p class="text-muted widget-intro-text">
|
|
8
|
+
Ingresa a la plataforma o regístrate y prueba una demo interactiva con nuestra empresa de ejemplo.
|
|
9
|
+
</p>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<!-- 2. Formulario de Inicio de Sesión -->
|
|
13
|
+
<form id="login-form"
|
|
14
|
+
action="{{ url_for('initiate_login', company_short_name=company_short_name) }}"
|
|
15
|
+
method="post">
|
|
16
|
+
<div class="mb-3">
|
|
17
|
+
<label for="email" class="form-label d-block text-muted">Correo Electrónico</label>
|
|
18
|
+
<input type="email" id="email" name="email" class="form-control" required>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="mb-3">
|
|
21
|
+
<label for="password" class="form-label d-block text-muted">Contraseña</label>
|
|
22
|
+
<input type="password" id="password" name="password"
|
|
23
|
+
class="form-control" required>
|
|
24
|
+
</div>
|
|
25
|
+
<button type="submit" class="btn btn-branded-primary w-100 fw-bold py-2">
|
|
26
|
+
Ingresar
|
|
27
|
+
</button>
|
|
28
|
+
</form>
|
|
29
|
+
|
|
30
|
+
<!-- 3. Nueva Sección de Registro más Atractiva -->
|
|
31
|
+
<div class="mt-4 pt-3 text-center" style="border-top: 1px solid #e0e0e0;">
|
|
32
|
+
<span class="text-muted small">¿Eres nuevo aquí?</span>
|
|
33
|
+
<a href="{{ url_for('signup', company_short_name=company_short_name) }}" id="signup-link" class="fw-bold ms-1 text-decoration-none">Crea una cuenta gratis</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
|
+
¿Olvidaste tu contraseña?
|
|
40
|
+
</a>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<!-- templates/_navbar.html -->
|
|
2
|
+
<nav class="navbar landing-navbar">
|
|
3
|
+
<div class="container-fluid">
|
|
4
|
+
<!-- Convertido en un enlace a la landing page de la compañía actual -->
|
|
5
|
+
<a class="navbar-brand text-decoration-none" href="{{ url_for('index', company_short_name=company_short_name) }}">
|
|
6
|
+
IAToolkit
|
|
7
|
+
</a>
|
|
8
|
+
</div>
|
|
9
|
+
</nav>
|
|
@@ -14,10 +14,12 @@
|
|
|
14
14
|
<link rel="stylesheet" href="{{ url_for('static', filename='styles/llm_output.css', _external=True) }}">
|
|
15
15
|
</head>
|
|
16
16
|
<body class="d-flex flex-column p-3" style="min-height: 100vh;">
|
|
17
|
+
|
|
17
18
|
<main class="d-flex flex-column flex-grow-1">
|
|
18
19
|
{% block content %}{% endblock %}
|
|
19
20
|
</main>
|
|
20
21
|
|
|
22
|
+
|
|
21
23
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js"></script>
|
|
22
24
|
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
|
23
25
|
<script src="https://cdn.jsdelivr.net/npm/filepond/dist/filepond.min.js"></script>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Cambiar Contraseña - {{ company.name }}{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<!-- 1. Incluimos los estilos de branding reutilizables -->
|
|
7
|
+
{% include '_branding_styles.html' %}
|
|
8
|
+
|
|
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">
|
|
11
|
+
|
|
12
|
+
<!-- 2. Incluimos la barra de navegación reutilizable -->
|
|
13
|
+
{% include '_navbar.html' %}
|
|
14
|
+
|
|
15
|
+
<!-- 3. Sección contenedora para centrar el contenido -->
|
|
16
|
+
<section class="hero-section">
|
|
17
|
+
<div class="container">
|
|
18
|
+
<div class="row justify-content-center">
|
|
19
|
+
<div class="col-lg-6 col-md-8">
|
|
20
|
+
<div class="border rounded p-4 p-md-5 shadow-sm bg-light">
|
|
21
|
+
<h4 class="form-title fw-bold mb-3 text-center">Crear Nueva Contraseña</h4>
|
|
22
|
+
|
|
23
|
+
<p class="text-muted text-center mb-4">
|
|
24
|
+
Estás cambiando la contraseña para <strong>{{ email }}</strong>.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<form action="{{ url_for('change_password', company_short_name=company_short_name, token=token) }}" method="post">
|
|
28
|
+
|
|
29
|
+
<!-- CAMPO RESTAURADO: Código Temporal -->
|
|
30
|
+
<div class="mb-3">
|
|
31
|
+
<label for="temp_code" class="form-label text-secondary">Código Temporal</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="Revisa tu correo electrónico">
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="mb-3">
|
|
38
|
+
<label for="new_password" class="form-label text-secondary">Nueva Contraseña</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>Debe contener al menos 8 caracteres, mayúscula, minúscula, número y un carácter especial.</span>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<div class="mb-3">
|
|
47
|
+
<label for="confirm_password" class="form-label text-secondary">Confirmar Nueva Contraseña</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">Guardar Contraseña</button>
|
|
52
|
+
</form>
|
|
53
|
+
|
|
54
|
+
<div class="text-center mt-4 pt-3" style="border-top: 1px solid #e0e0e0;">
|
|
55
|
+
<a href="{{ url_for('index', 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
|
|
57
|
+
</a>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</section>
|
|
64
|
+
{% endblock %}
|
|
@@ -118,8 +118,9 @@
|
|
|
118
118
|
<div id="chat-input-bar" class="chat-input-bar d-flex align-items-center">
|
|
119
119
|
<!-- Iconos de la izquierda -->
|
|
120
120
|
<div class="d-flex align-items-center">
|
|
121
|
-
<!--
|
|
122
|
-
<a class="p-2" href="#prompt-assistant-collapse" data-bs-toggle="collapse" role="button"
|
|
121
|
+
<!-- varita magica -->
|
|
122
|
+
<a class="p-2" href="#prompt-assistant-collapse" data-bs-toggle="collapse" role="button"
|
|
123
|
+
aria-expanded="false" aria-controls="prompt-assistant-collapse" title="Usar Asistente de Prompts">
|
|
123
124
|
<i class="bi bi-magic"></i>
|
|
124
125
|
</a>
|
|
125
126
|
<a class="p-2" href="javascript:void(0);" id="paperclip-button" title="Adjuntar archivos">
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Recuperar Contraseña - {{ company.name }}{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<!-- 1. Incluimos los estilos de branding reutilizables -->
|
|
7
|
+
{% include '_branding_styles.html' %}
|
|
8
|
+
|
|
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">
|
|
11
|
+
|
|
12
|
+
<!-- 2. Incluimos la barra de navegación reutilizable -->
|
|
13
|
+
{% include '_navbar.html' %}
|
|
14
|
+
|
|
15
|
+
<!-- 3. Sección contenedora para centrar el contenido -->
|
|
16
|
+
<section class="hero-section">
|
|
17
|
+
<div class="container">
|
|
18
|
+
<div class="row justify-content-center">
|
|
19
|
+
<div class="col-lg-6 col-md-8">
|
|
20
|
+
<div class="border rounded p-4 p-md-5 shadow-sm bg-light">
|
|
21
|
+
<h4 class="form-title fw-bold mb-3 text-center">Recuperar Contraseña</h4>
|
|
22
|
+
|
|
23
|
+
<p class="text-muted text-center mb-4">
|
|
24
|
+
Ingresa tu correo electrónico y te enviaremos un enlace para restablecer tu contraseña.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<form action="{{ url_for('forgot_password', company_short_name=company_short_name) }}" method="post">
|
|
28
|
+
<div class="mb-3">
|
|
29
|
+
<label for="email" class="form-label text-secondary">Correo Electrónico</label>
|
|
30
|
+
<input type="email" id="email" name="email"
|
|
31
|
+
class="form-control"
|
|
32
|
+
required value="{{ form_data.email if form_data else '' }}">
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<button type="submit" class="btn btn-branded-primary w-100 fw-bold py-2 mt-3">Enviar Enlace</button>
|
|
36
|
+
</form>
|
|
37
|
+
|
|
38
|
+
<div class="text-center mt-4 pt-3" style="border-top: 1px solid #e0e0e0;">
|
|
39
|
+
<a href="{{ url_for('index', company_short_name=company_short_name) }}" class="text-muted text-decoration-none fw-semibold">
|
|
40
|
+
<i class="bi bi-arrow-left me-1"></i>Volver al inicio
|
|
41
|
+
</a>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</section>
|
|
48
|
+
{% endblock %}
|