iatoolkit 0.51.0__tar.gz → 0.55.1__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.

Potentially problematic release.


This version of iatoolkit might be problematic. Click here for more details.

Files changed (128) hide show
  1. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/PKG-INFO +1 -1
  2. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/pyproject.toml +1 -1
  3. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/common/routes.py +3 -2
  4. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/iatoolkit.py +1 -1
  5. iatoolkit-0.55.1/src/iatoolkit/static/js/chat_onboarding.js +98 -0
  6. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -1
  7. iatoolkit-0.55.1/src/iatoolkit/static/styles/onboarding.css +169 -0
  8. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/base.html +1 -0
  9. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/chat.html +59 -15
  10. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/chat_modals.html +33 -0
  11. iatoolkit-0.55.1/src/iatoolkit/templates/login_test.html +118 -0
  12. iatoolkit-0.55.1/src/iatoolkit/templates/onboarding_shell.html +105 -0
  13. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/base_login_view.py +8 -3
  14. iatoolkit-0.55.1/src/iatoolkit/views/login_simulation_view.py +60 -0
  15. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/login_view.py +7 -2
  16. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit.egg-info/PKG-INFO +1 -1
  17. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit.egg-info/SOURCES.txt +3 -1
  18. iatoolkit-0.51.0/src/iatoolkit/templates/login_test.html +0 -150
  19. iatoolkit-0.51.0/src/iatoolkit/templates/onboarding_shell.html +0 -167
  20. iatoolkit-0.51.0/src/iatoolkit/views/login_test_view.py +0 -31
  21. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/readme.md +0 -0
  22. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/requirements.txt +0 -0
  23. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/setup.cfg +0 -0
  24. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/__init__.py +0 -0
  25. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/base_company.py +0 -0
  26. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/cli_commands.py +0 -0
  27. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/common/__init__.py +0 -0
  28. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/common/exceptions.py +0 -0
  29. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/common/session_manager.py +0 -0
  30. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/common/util.py +0 -0
  31. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/company_registry.py +0 -0
  32. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/__init__.py +0 -0
  33. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/call_service.py +0 -0
  34. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  35. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  36. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  37. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  38. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  39. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  40. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  41. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/gemini_adapter.py +0 -0
  42. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/google_chat_app.py +0 -0
  43. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/llm_client.py +0 -0
  44. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/llm_proxy.py +0 -0
  45. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/llm_response.py +0 -0
  46. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/mail_app.py +0 -0
  47. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/openai_adapter.py +0 -0
  48. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  49. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/__init__.py +0 -0
  50. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/database_manager.py +0 -0
  51. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/document_repo.py +0 -0
  52. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  53. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/models.py +0 -0
  54. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/profile_repo.py +0 -0
  55. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/tasks_repo.py +0 -0
  56. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/repositories/vs_repo.py +0 -0
  57. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/__init__.py +0 -0
  58. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/auth_service.py +0 -0
  59. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/benchmark_service.py +0 -0
  60. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/branding_service.py +0 -0
  61. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/dispatcher_service.py +0 -0
  62. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/document_service.py +0 -0
  63. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/excel_service.py +0 -0
  64. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/file_processor_service.py +0 -0
  65. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/history_service.py +0 -0
  66. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/jwt_service.py +0 -0
  67. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/load_documents_service.py +0 -0
  68. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/mail_service.py +0 -0
  69. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/onboarding_service.py +0 -0
  70. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/profile_service.py +0 -0
  71. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/prompt_manager_service.py +0 -0
  72. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/query_service.py +0 -0
  73. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/search_service.py +0 -0
  74. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/sql_service.py +0 -0
  75. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/tasks_service.py +0 -0
  76. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/user_feedback_service.py +0 -0
  77. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/services/user_session_context_service.py +0 -0
  78. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/arrow_up.png +0 -0
  79. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/diagrama_iatoolkit.jpg +0 -0
  80. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/logo_clinica.png +0 -0
  81. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/logo_iatoolkit.png +0 -0
  82. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/logo_maxxa.png +0 -0
  83. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/logo_notaria.png +0 -0
  84. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/logo_tarjeta.png +0 -0
  85. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/logo_umayor.png +0 -0
  86. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/images/upload.png +0 -0
  87. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/js/chat_feedback.js +0 -0
  88. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  89. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/js/chat_history.js +0 -0
  90. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/js/chat_main.js +0 -0
  91. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/styles/chat_info.css +0 -0
  92. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  93. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/styles/landing_page.css +0 -0
  94. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/static/styles/llm_output.css +0 -0
  95. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
  96. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
  97. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
  98. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/_branding_styles.html +0 -0
  99. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/_login_widget.html +0 -0
  100. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/_navbar.html +0 -0
  101. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/about.html +0 -0
  102. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/change_password.html +0 -0
  103. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/error.html +0 -0
  104. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/forgot_password.html +0 -0
  105. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/header.html +0 -0
  106. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/index.html +0 -0
  107. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/signup.html +0 -0
  108. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/templates/test.html +0 -0
  109. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/__init__.py +0 -0
  110. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/change_password_view.py +0 -0
  111. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/chat_token_request_view.py +0 -0
  112. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/external_login_view.py +0 -0
  113. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/file_store_api_view.py +0 -0
  114. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/forgot_password_view.py +0 -0
  115. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/history_api_view.py +0 -0
  116. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/index_view.py +0 -0
  117. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/init_context_api_view.py +0 -0
  118. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  119. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/llmquery_web_view.py +0 -0
  120. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/prompt_api_view.py +0 -0
  121. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/signup_view.py +0 -0
  122. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/tasks_review_view.py +0 -0
  123. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/tasks_view.py +0 -0
  124. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  125. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit/views/verify_user_view.py +0 -0
  126. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  127. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit.egg-info/requires.txt +0 -0
  128. {iatoolkit-0.51.0 → iatoolkit-0.55.1}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 0.51.0
3
+ Version: 0.55.1
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "iatoolkit"
7
- version = "0.51.0"
7
+ version = "0.55.1"
8
8
  requires-python = ">=3.12"
9
9
  description = "IAToolkit"
10
10
  readme = "readme.md"
@@ -25,7 +25,7 @@ def register_views(injector, app):
25
25
  from iatoolkit.views.llmquery_api_view import LLMQueryApiView
26
26
  from iatoolkit.views.tasks_view import TaskView
27
27
  from iatoolkit.views.tasks_review_view import TaskReviewView
28
- from iatoolkit.views.login_test_view import LoginTest
28
+ from iatoolkit.views.login_simulation_view import LoginSimulationView
29
29
  from iatoolkit.views.login_view import LoginView, FinalizeContextView
30
30
  from iatoolkit.views.external_login_view import ExternalLoginView
31
31
  from iatoolkit.views.signup_view import SignupView
@@ -112,7 +112,8 @@ def register_views(injector, app):
112
112
  abort(404)
113
113
 
114
114
  # login testing (old home page)
115
- app.add_url_rule('/login_test', view_func=LoginTest.as_view('login_test'))
115
+ app.add_url_rule('/login_test/<company_short_name>/<external_user_id>',
116
+ view_func=LoginSimulationView.as_view('login_test'))
116
117
 
117
118
  app.add_url_rule(
118
119
  '/about', # URL de la ruta
@@ -19,7 +19,7 @@ from werkzeug.middleware.proxy_fix import ProxyFix
19
19
  from injector import Binder, singleton, Injector
20
20
  from importlib.metadata import version as _pkg_version, PackageNotFoundError
21
21
 
22
- IATOOLKIT_VERSION = "0.50.2"
22
+ IATOOLKIT_VERSION = "0.55.1"
23
23
 
24
24
  # global variable for the unique instance of IAToolkit
25
25
  _iatoolkit_instance: Optional['IAToolkit'] = None
@@ -0,0 +1,98 @@
1
+ // static/js/chat_onboarding.js
2
+ (function (global) {
3
+ function qs(root, sel) { return (typeof sel === 'string') ? root.querySelector(sel) : sel; }
4
+
5
+ function createDots(container, count, activeIdx, activeColor) {
6
+ container.innerHTML = '';
7
+ for (let i = 0; i < count; i++) {
8
+ const d = document.createElement('div');
9
+ if (i === activeIdx) d.classList.add('active');
10
+ d.style.width = '10px';
11
+ d.style.height = '10px';
12
+ d.style.borderRadius = '50%';
13
+ d.style.backgroundColor = i === activeIdx ? (activeColor || 'var(--brand-primary-color, #FF5100)') : '#ddd';
14
+ d.style.transition = 'background-color .3s';
15
+ container.appendChild(d);
16
+ }
17
+ }
18
+
19
+ function initOnboarding(opts) {
20
+ const {
21
+ mode = 'modal',
22
+ cards = [],
23
+ ui = {},
24
+ autoRotateMs = 5000,
25
+ shell = {}
26
+ } = opts;
27
+
28
+ const root = document;
29
+ const elIcon = qs(root, ui.icon);
30
+ const elTitle = qs(root, ui.title);
31
+ const elText = qs(root, ui.text);
32
+ const elDots = qs(root, ui.dots);
33
+ const elPrev = qs(root, ui.prev);
34
+ const elNext = qs(root, ui.next);
35
+
36
+ let idx = 0;
37
+ let autoTimer = null;
38
+
39
+ function hasCards() { return Array.isArray(cards) && cards.length > 0; }
40
+
41
+ function render() {
42
+ if (!hasCards()) return;
43
+ const c = cards[idx] || {};
44
+ if (elIcon) elIcon.innerHTML = `<i class="${c.icon || 'bi bi-lightbulb'}"></i>`;
45
+ if (elTitle) elTitle.textContent = c.title || '';
46
+ if (elText) elText.innerHTML = c.text || '';
47
+ if (elDots) createDots(elDots, cards.length, idx);
48
+ }
49
+
50
+ function next() { if (!hasCards()) return; idx = (idx + 1) % cards.length; render(); }
51
+ function prev() { if (!hasCards()) return; idx = (idx - 1 + cards.length) % cards.length; render(); }
52
+
53
+ function startAuto() {
54
+ stopAuto();
55
+ if (!hasCards()) return;
56
+ autoTimer = setInterval(next, autoRotateMs);
57
+ }
58
+ function stopAuto() { if (autoTimer) { clearInterval(autoTimer); autoTimer = null; } }
59
+
60
+ function setupShellIfNeeded() {
61
+ if (mode !== 'shell') return;
62
+ const loader = ui.loader ? qs(root, ui.loader) : null;
63
+ const container = ui.container ? qs(root, ui.container) : null;
64
+ if (!container || !shell.iframeSrc) return;
65
+
66
+ const iframe = document.createElement('iframe');
67
+ iframe.src = shell.iframeSrc;
68
+ iframe.style.width = '100%';
69
+ iframe.style.height = '100%';
70
+ iframe.style.border = 'none';
71
+ iframe.style.display = 'none';
72
+
73
+ iframe.onload = function () {
74
+ iframe.style.display = 'block';
75
+ if (loader) {
76
+ loader.style.opacity = '0';
77
+ setTimeout(() => loader.style.display = 'none', 500);
78
+ }
79
+ };
80
+ container.appendChild(iframe);
81
+ }
82
+
83
+ if (elPrev) elPrev.addEventListener('click', () => { prev(); startAuto(); });
84
+ if (elNext) elNext.addEventListener('click', () => { next(); startAuto(); });
85
+
86
+ function start() {
87
+ idx = 0;
88
+ render();
89
+ startAuto();
90
+ if (mode === 'shell') setupShellIfNeeded();
91
+ }
92
+
93
+ return { start, stop: stopAuto, next, prev, hasCards };
94
+ }
95
+
96
+ // Export global
97
+ global.initOnboarding = initOnboarding;
98
+ })(window);
@@ -455,4 +455,3 @@
455
455
  #send-button i {
456
456
  color: var(--brand-send-button-color);
457
457
  }
458
-
@@ -0,0 +1,169 @@
1
+ /* static/css/onboarding.css */
2
+
3
+ /* Fuente base para ambos contextos */
4
+ .ob-root {
5
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
6
+ }
7
+
8
+ /* Tarjeta */
9
+ .ob-card {
10
+ background-color: #fff;
11
+ border-radius: 12px;
12
+ box-shadow: 0 4px 20px rgba(0,0,0,0.1);
13
+ padding: 30px;
14
+ width: 90%;
15
+ max-width: 450px;
16
+ text-align: center;
17
+ transition: opacity 0.3s ease-in-out;
18
+ margin: 0 auto;
19
+ }
20
+
21
+ /* Contenido de tarjeta */
22
+ .ob-icon {
23
+ font-size: 40px;
24
+ color: var(--brand-primary-color, #FF5100);
25
+ margin-bottom: 15px;
26
+ }
27
+ .ob-title {
28
+ font-size: 1.25rem;
29
+ color: #333;
30
+ margin-bottom: 10px;
31
+ }
32
+ .ob-text {
33
+ font-size: 0.95rem;
34
+ color: #666;
35
+ line-height: 1.5;
36
+ min-height: 60px;
37
+ }
38
+
39
+ /* Navegación */
40
+ .ob-nav {
41
+ display: flex;
42
+ justify-content: space-between;
43
+ align-items: center;
44
+ margin-top: 20px;
45
+ }
46
+ .ob-btn {
47
+ background-color: var(--brand-secondary-color, #06326B);
48
+ border: none;
49
+ color: var(--brand-text-on-secondary, #FFFFFF);
50
+ border-radius: 50%;
51
+ width: 40px;
52
+ height: 40px;
53
+ cursor: pointer;
54
+ transition: opacity 0.2s;
55
+ display: inline-flex;
56
+ align-items: center;
57
+ justify-content: center;
58
+ }
59
+ .ob-btn:hover { opacity: 0.85; }
60
+
61
+ /* Dots */
62
+ .ob-dots {
63
+ display: flex;
64
+ gap: 8px;
65
+ }
66
+ .ob-dots > div {
67
+ width: 10px;
68
+ height: 10px;
69
+ border-radius: 50%;
70
+ background-color: #ddd;
71
+ transition: background-color 0.3s;
72
+ }
73
+ .ob-dots > div.active {
74
+ background-color: var(--brand-primary-color, #FF5100);
75
+ }
76
+
77
+ /* Encabezado reutilizable (si se usa) */
78
+ .ob-brand-header {
79
+ font-size: 2rem;
80
+ font-weight: 700;
81
+ margin-bottom: 24px;
82
+ color: var(--brand-secondary-color, #06326B);
83
+ text-align: center;
84
+ }
85
+ .ob-brand-header .brand-name {
86
+ color: var(--brand-primary-color, #FF5100);
87
+ }
88
+
89
+ /* Utilidades */
90
+ .ob-fade {
91
+ transition: opacity 0.5s ease-in-out;
92
+ }
93
+
94
+ /* Responsivo */
95
+ @media (max-width: 420px) {
96
+ .ob-card { padding: 24px; }
97
+ .ob-icon { font-size: 34px; }
98
+ }
99
+
100
+ /* Overlay a pantalla completa */
101
+ .onboarding-shell-root {
102
+ position: relative;
103
+ height: calc(100vh - 0px);
104
+ }
105
+
106
+ /* Centrado vertical y horizontal del contenido del loader */
107
+ #loader-wrapper {
108
+ position: absolute; inset: 0;
109
+ background-color: #f4f7f6;
110
+ z-index: 1000;
111
+ display: flex; align-items: center; justify-content: center;
112
+ padding: 20px; box-sizing: border-box;
113
+ transition: opacity 0.5s ease-in-out;
114
+ }
115
+
116
+ /* Pila vertical: header + tarjeta + banda de carga */
117
+ .ob-stack {
118
+ width: 100%;
119
+ max-width: 520px; /* ligeramente más que la tarjeta para respiración */
120
+ display: flex;
121
+ flex-direction: column;
122
+ align-items: stretch; /* la tarjeta ocupa el ancho */
123
+ gap: 16px;
124
+ }
125
+
126
+ /* Header de marca consistente */
127
+ .ob-brand-header {
128
+ font-size: 2rem;
129
+ font-weight: 700;
130
+ margin: 0;
131
+ color: var(--brand-secondary-color, #06326B);
132
+ text-align: center;
133
+ }
134
+ .ob-brand-header .brand-name {
135
+ color: var(--brand-primary-color, #FF5100);
136
+ }
137
+
138
+ /* Banda de estado integrada visualmente con la tarjeta */
139
+ .ob-loading-band {
140
+ display: flex;
141
+ align-items: center;
142
+ justify-content: center;
143
+ gap: 12px;
144
+ padding: 12px 14px;
145
+ background: #ffffff;
146
+ border-radius: 12px;
147
+ box-shadow: 0 4px 20px rgba(0,0,0,0.08);
148
+ }
149
+
150
+ /* Spinner */
151
+ .spinner {
152
+ width: 28px; height: 28px;
153
+ border: 4px solid rgba(0,0,0,0.1);
154
+ border-top-color: var(--brand-primary-color, #FF5100);
155
+ border-radius: 50%;
156
+ animation: spin 1s linear infinite;
157
+ }
158
+ @keyframes spin { to { transform: rotate(360deg); } }
159
+
160
+ #loading-status p {
161
+ font-size: 0.95rem;
162
+ font-weight: 500;
163
+ color: #555;
164
+ margin: 0;
165
+ }
166
+
167
+ /* Iframe contenedor */
168
+ #content-container { width: 100%; height: 100%; }
169
+ #content-container iframe { width: 100%; height: 100%; border: none; }
@@ -10,6 +10,7 @@
10
10
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/filepond/dist/filepond.min.css">
11
11
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css">
12
12
  <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_iatoolkit.css', _external=True) }}">
13
+ <link rel="stylesheet" href="{{ url_for('static', filename='styles/onboarding.css', _external=True) }}">
13
14
  <link rel="stylesheet" href="{{ url_for('static', filename='styles/chat_modal.css', _external=True) }}">
14
15
  <link rel="stylesheet" href="{{ url_for('static', filename='styles/llm_output.css', _external=True) }}">
15
16
  </head>
@@ -4,9 +4,15 @@
4
4
 
5
5
  {% block content %}
6
6
 
7
- <style>
8
- {{ branding.css_variables | safe }}
9
- </style>
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="{{ url_for('static', filename='styles/onboarding.css', _external=True) }}">
13
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
14
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
15
+ {% endblock %}
10
16
 
11
17
  <!-- Sección de encabezado con el usuario conectado -->
12
18
  <div id="company-section" class="company-section d-flex justify-content-between align-items-center px-3 py-2"
@@ -49,14 +55,17 @@
49
55
  class="ms-3 action-icon-style" title="Tu feedback es muy importante" style="color: {{ branding.header_text_color }};">
50
56
  <i class="bi bi-emoji-smile"></i>
51
57
  </a>
58
+ <a href="javascript:void(0);" id="onboarding-button"
59
+ class="ms-3 action-icon-style" title="Ver onboarding"
60
+ style="color: {{ branding.header_text_color }};">
61
+ <i class="bi bi-lightbulb"></i>
62
+ </a>
52
63
 
53
64
  <!-- Icono de cerrar sesión (al final) -->
54
- {% if user_is_local %}
55
- <a href="{{ url_for('logout', company_short_name=company_short_name, _external=True) }}"
56
- class="ms-3 action-icon-style" title="Cerrar sesión" style="color: {{ branding.header_text_color }} !important;">
57
- <i class="bi bi-box-arrow-right"></i>
58
- </a>
59
- {% endif %}
65
+ <a href="{{ url_for('logout', company_short_name=company_short_name, _external=True) }}"
66
+ class="ms-3 action-icon-style" title="Cerrar sesión" style="color: {{ branding.header_text_color }} !important;">
67
+ <i class="bi bi-box-arrow-right"></i>
68
+ </a>
60
69
  </div>
61
70
 
62
71
  </div>
@@ -174,20 +183,16 @@
174
183
  window.iatoolkit_base_url = "{{ iatoolkit_base_url }}";
175
184
  window.availablePrompts = {{ prompts.message | tojson }};
176
185
  window.sendButtonColor = "{{ branding.send_button_color }}";
177
-
178
- {% if auth_method == 'jwt' and session_jwt %}
179
- // Store session JWT if it exists, defined in the same global scope
180
- window.sessionJWT = "{{ session_jwt }}";
181
- {% endif %}
186
+ window.onboardingCards = {{ onboarding_cards | tojson }};
182
187
  </script>
183
188
 
184
189
  <!-- Carga de los scripts JS externos después de definir las variables globales -->
190
+ <script src="{{ url_for('static', filename='js/chat_onboarding.js', _external=True) }}"></script>
185
191
  <script src="{{ url_for('static', filename='js/chat_filepond.js', _external=True) }}"></script>
186
192
  <script src="{{ url_for('static', filename='js/chat_history.js', _external=True) }}"></script>
187
193
  <script src="{{ url_for('static', filename='js/chat_feedback.js', _external=True) }}"></script>
188
194
  <script src="{{ url_for('static', filename='js/chat_main.js', _external=True) }}"></script>
189
195
 
190
-
191
196
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
192
197
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
193
198
  <script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
@@ -274,5 +279,44 @@ document.addEventListener('DOMContentLoaded', function() {
274
279
  });
275
280
  });
276
281
  });
282
+
283
+ // Inicialización del modal de onboarding
284
+ document.addEventListener('DOMContentLoaded', function () {
285
+ const btn = document.getElementById('onboarding-button');
286
+ if (!btn) return;
287
+
288
+ const modalEl = document.getElementById('onboardingModal');
289
+ const modal = new bootstrap.Modal(modalEl);
290
+
291
+ if (!window.initOnboarding) {
292
+ console.error('initOnboarding no disponible. Verifica chat_onboarding.js');
293
+ return;
294
+ }
295
+
296
+ const onboarding = initOnboarding({
297
+ mode: 'modal',
298
+ cards: Array.isArray(window.onboardingCards) ? window.onboardingCards : [],
299
+ ui: {
300
+ icon: '#ob-icon',
301
+ title: '#ob-title',
302
+ text: '#ob-text',
303
+ dots: '#ob-dots',
304
+ prev: '#ob-prev',
305
+ next: '#ob-next'
306
+ },
307
+ autoRotateMs: 5000
308
+ });
309
+
310
+ modalEl.addEventListener('hidden.bs.modal', () => onboarding.stop());
311
+
312
+ btn.addEventListener('click', () => {
313
+ if (!onboarding.hasCards()) {
314
+ toastr.info('No hay información de onboarding disponible.');
315
+ return;
316
+ }
317
+ onboarding.start();
318
+ modal.show();
319
+ });
320
+ });
277
321
  </script>
278
322
  {% endblock %}
@@ -109,4 +109,37 @@
109
109
  </div>
110
110
  </div>
111
111
  </div>
112
+ </div>
113
+
114
+ <!-- Modal de Onboarding -->
115
+ <div class="modal fade" id="onboardingModal" tabindex="-1" aria-labelledby="onboardingModalLabel" aria-hidden="true">
116
+ <div class="modal-dialog modal-dialog-centered">
117
+ <div class="modal-content" style="border-radius:12px;">
118
+ <div class="modal-header">
119
+ <h5 class="modal-title w-100 text-center" id="onboardingModalLabel" style="color: var(--brand-primary-color, #FF5100);">
120
+ Bienvenido a {{ branding.name }}
121
+ </h5>
122
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
123
+ </div>
124
+
125
+ <div class="modal-body ob-root">
126
+ <div id="ob-card" class="ob-card">
127
+ <div id="ob-icon" class="ob-icon"><i class="bi bi-lightbulb"></i></div>
128
+ <h6 id="ob-title" class="ob-title"></h6>
129
+ <div id="ob-text" class="ob-text"></div>
130
+ <div class="ob-nav">
131
+ <button id="ob-prev" class="ob-btn" aria-label="Anterior"><i class="bi bi-chevron-left"></i></button>
132
+ <div id="ob-dots" class="ob-dots"></div>
133
+ <button id="ob-next" class="ob-btn" aria-label="Siguiente"><i class="bi bi-chevron-right"></i></button>
134
+ </div>
135
+ </div>
136
+ </div>
137
+
138
+ <div class="modal-footer">
139
+ <button id="ob-close" type="button" class="btn btn-branded-primary" data-bs-dismiss="modal">
140
+ Cerrar
141
+ </button>
142
+ </div>
143
+ </div>
144
+ </div>
112
145
  </div>
@@ -0,0 +1,118 @@
1
+ {% extends "base.html" %}
2
+
3
+ {% block title %}Prueba de Login para {{ branding.name }}{% endblock %}
4
+
5
+ {% block styles %}
6
+ {# Este bloque asegura que los colores de la marca estén disponibles como variables CSS #}
7
+ {% if branding and branding.css_variables %}
8
+ <style>
9
+ {{ branding.css_variables|safe }}
10
+ /* Usa la variable de CSS para el color primario del botón */
11
+ #initiateJwtChatButton {
12
+ background-color: var(--brand-primary-color, #0d6efd);
13
+ border-color: var(--brand-primary-color, #0d6efd);
14
+ }
15
+ </style>
16
+ {% endif %}
17
+ {% endblock %}
18
+
19
+ {% block content %}
20
+ <div class="container-fluid">
21
+ <div class="row flex-fill mt-5 justify-content-center">
22
+ <!-- login desde sistema externo -->
23
+ <div class="col-12 col-lg-6">
24
+ <div class="border rounded p-4 p-md-5 shadow-sm bg-light">
25
+ {# El título ahora muestra dinámicamente el nombre de la empresa #}
26
+ <h3 class="text-muted fw-semibold text-start mb-3">
27
+ Login Externo para <span style="color: var(--brand-primary-color, #0d6efd);">{{ branding.name }}</span>
28
+ </h3>
29
+ <div class="text-center mb-4">
30
+ <p class="text-muted widget-intro-text">
31
+ Este formulario permite testear el acceso a IAToolkit desde un portal externo utilizando una api-key. El external user ID es el nombre del usuario ya autentificado en algún portal interno de la empresa.
32
+ </p>
33
+ </div>
34
+
35
+ {# El 'action' y 'method' son manejados por JS, pero el id es crucial #}
36
+ <form id="jwt-form">
37
+
38
+ <div class="mb-3">
39
+ <label for="external_user_id" class="form-label d-block">External user ID</label>
40
+ <input type="text" id="external_user_id" name="external_user_id" class="form-control" required>
41
+ </div>
42
+
43
+ <button type="submit" id="initiateJwtChatButton" class="btn btn-primary">
44
+ <span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
45
+ Iniciar Sesión
46
+ </button>
47
+ </form>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ {% endblock %}
53
+
54
+ {% block scripts %}
55
+ <script>
56
+ document.addEventListener('DOMContentLoaded', function() {
57
+ const companyShortName = "{{ company_short_name }}";
58
+ const apiKey = "{{ api_key }}";
59
+ const loginForm = document.getElementById('jwt-form');
60
+ const userIdInput = document.getElementById('external_user_id');
61
+ const submitButton = document.getElementById('initiateJwtChatButton');
62
+ const spinner = submitButton.querySelector('.spinner-border');
63
+
64
+ loginForm.addEventListener('submit', function(event) {
65
+ event.preventDefault();
66
+ const userIdentifier = userIdInput.value.trim();
67
+ if (!userIdentifier) return;
68
+
69
+ // Deshabilitar botón y mostrar spinner
70
+ submitButton.disabled = true;
71
+ spinner.classList.remove('d-none');
72
+
73
+ const newWindow = window.open('', '_blank');
74
+ const apiUrl = `/${companyShortName}/external_login`;
75
+
76
+ fetch(apiUrl, {
77
+ method: 'POST',
78
+ headers: {
79
+ 'Content-Type': 'application/json',
80
+ 'Authorization': `Bearer ${apiKey}`
81
+ },
82
+ body: JSON.stringify({ external_user_id: userIdentifier })
83
+ })
84
+ .then(response => response.ok ? response.text() : response.text().then(text => { throw new Error(text) }))
85
+ .then(html => {
86
+ newWindow.document.documentElement.innerHTML = html;
87
+ // Buscamos todos los scripts en el HTML inyectado y los re-ejecutamos.
88
+ const scripts = newWindow.document.querySelectorAll('script');
89
+ scripts.forEach(oldScript => {
90
+ const newScript = newWindow.document.createElement('script');
91
+
92
+ // Copiamos los atributos (como 'src' para archivos externos)
93
+ Array.from(oldScript.attributes).forEach(attr => {
94
+ newScript.setAttribute(attr.name, attr.value);
95
+ });
96
+
97
+ // Copiamos el contenido para scripts inline
98
+ newScript.appendChild(newWindow.document.createTextNode(oldScript.innerHTML));
99
+
100
+ // Reemplazamos el script viejo por el nuevo para que se ejecute.
101
+ oldScript.parentNode.replaceChild(newScript, oldScript);
102
+ });
103
+
104
+ })
105
+ .catch(error => {
106
+ console.error("Falló la prueba de login externo:", error);
107
+ const errorMessage = error.message || "Error desconocido.";
108
+ newWindow.document.body.innerHTML = `<div style="padding: 20px; font-family: monospace;"><h2>Error</h2><pre>${errorMessage}</pre></div>`;
109
+ })
110
+ .finally(() => {
111
+ // Volver a habilitar el botón y ocultar el spinner
112
+ submitButton.disabled = false;
113
+ spinner.classList.add('d-none');
114
+ });
115
+ });
116
+ });
117
+ </script>
118
+ {% endblock %}