iatoolkit 0.50.2__py3-none-any.whl → 0.55.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of iatoolkit might be problematic. Click here for more details.
- iatoolkit/common/routes.py +5 -5
- iatoolkit/iatoolkit.py +7 -1
- iatoolkit/static/js/chat_onboarding.js +98 -0
- iatoolkit/static/styles/chat_iatoolkit.css +0 -1
- iatoolkit/static/styles/onboarding.css +169 -0
- iatoolkit/templates/_login_widget.html +1 -1
- iatoolkit/templates/base.html +1 -0
- iatoolkit/templates/chat.html +49 -6
- iatoolkit/templates/chat_modals.html +33 -0
- iatoolkit/templates/login_test.html +2 -2
- iatoolkit/templates/onboarding_shell.html +97 -163
- iatoolkit/views/base_login_view.py +68 -0
- iatoolkit/views/external_login_view.py +30 -53
- iatoolkit/views/login_test_view.py +16 -1
- iatoolkit/views/login_view.py +31 -74
- {iatoolkit-0.50.2.dist-info → iatoolkit-0.55.0.dist-info}/METADATA +1 -1
- {iatoolkit-0.50.2.dist-info → iatoolkit-0.55.0.dist-info}/RECORD +19 -16
- {iatoolkit-0.50.2.dist-info → iatoolkit-0.55.0.dist-info}/WHEEL +0 -0
- {iatoolkit-0.50.2.dist-info → iatoolkit-0.55.0.dist-info}/top_level.txt +0 -0
iatoolkit/common/routes.py
CHANGED
|
@@ -26,8 +26,8 @@ def register_views(injector, app):
|
|
|
26
26
|
from iatoolkit.views.tasks_view import TaskView
|
|
27
27
|
from iatoolkit.views.tasks_review_view import TaskReviewView
|
|
28
28
|
from iatoolkit.views.login_test_view import LoginTest
|
|
29
|
-
from iatoolkit.views.login_view import LoginView,
|
|
30
|
-
from iatoolkit.views.external_login_view import
|
|
29
|
+
from iatoolkit.views.login_view import LoginView, FinalizeContextView
|
|
30
|
+
from iatoolkit.views.external_login_view import ExternalLoginView
|
|
31
31
|
from iatoolkit.views.signup_view import SignupView
|
|
32
32
|
from iatoolkit.views.verify_user_view import VerifyAccountView
|
|
33
33
|
from iatoolkit.views.forgot_password_view import ForgotPasswordView
|
|
@@ -46,8 +46,8 @@ def register_views(injector, app):
|
|
|
46
46
|
|
|
47
47
|
# this functions are for login external users (with api-key)
|
|
48
48
|
# only the first one should be used from an external app
|
|
49
|
-
app.add_url_rule('/<company_short_name>/
|
|
50
|
-
view_func=
|
|
49
|
+
app.add_url_rule('/<company_short_name>/external_login',
|
|
50
|
+
view_func=ExternalLoginView.as_view('external_login'))
|
|
51
51
|
|
|
52
52
|
# this endpoint is for requesting a chat token for external users
|
|
53
53
|
app.add_url_rule('/auth/chat_token',
|
|
@@ -55,8 +55,8 @@ def register_views(injector, app):
|
|
|
55
55
|
|
|
56
56
|
# login for the iatoolkit integrated frontend
|
|
57
57
|
# this is the main login endpoint for the frontend
|
|
58
|
-
app.add_url_rule('/<company_short_name>/chat', view_func=InitiateLoginView.as_view('chat'))
|
|
59
58
|
app.add_url_rule('/<company_short_name>/login', view_func=LoginView.as_view('login'))
|
|
59
|
+
app.add_url_rule('/<company_short_name>/finalize_context_load', view_func=FinalizeContextView.as_view('finalize_context_load'))
|
|
60
60
|
|
|
61
61
|
# register new user, account verification and forgot password
|
|
62
62
|
app.add_url_rule('/<company_short_name>/signup',view_func=SignupView.as_view('signup'))
|
iatoolkit/iatoolkit.py
CHANGED
|
@@ -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.
|
|
22
|
+
IATOOLKIT_VERSION = "0.55.0"
|
|
23
23
|
|
|
24
24
|
# global variable for the unique instance of IAToolkit
|
|
25
25
|
_iatoolkit_instance: Optional['IAToolkit'] = None
|
|
@@ -360,6 +360,10 @@ class IAToolkit:
|
|
|
360
360
|
@self.app.context_processor
|
|
361
361
|
def inject_globals():
|
|
362
362
|
from iatoolkit.common.session_manager import SessionManager
|
|
363
|
+
from iatoolkit.services.profile_service import ProfileService
|
|
364
|
+
|
|
365
|
+
profile_service = self._injector.get(ProfileService)
|
|
366
|
+
user_profile = profile_service.get_current_session_info().get('profile', {})
|
|
363
367
|
|
|
364
368
|
return {
|
|
365
369
|
'url_for': url_for,
|
|
@@ -367,6 +371,8 @@ class IAToolkit:
|
|
|
367
371
|
'app_name': 'IAToolkit',
|
|
368
372
|
'user_identifier': SessionManager.get('user_identifier'),
|
|
369
373
|
'company_short_name': SessionManager.get('company_short_name'),
|
|
374
|
+
'user_is_local': user_profile.get('user_is_local'),
|
|
375
|
+
'user_email': user_profile.get('user_email'),
|
|
370
376
|
'iatoolkit_base_url': os.environ.get('IATOOLKIT_BASE_URL', ''),
|
|
371
377
|
}
|
|
372
378
|
|
|
@@ -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);
|
|
@@ -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,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
<!-- 2. Formulario de Inicio de Sesión -->
|
|
12
12
|
<form id="login-form"
|
|
13
|
-
action="{{ url_for('
|
|
13
|
+
action="{{ url_for('login', company_short_name=company_short_name) }}"
|
|
14
14
|
method="post">
|
|
15
15
|
<div class="mb-3">
|
|
16
16
|
<label for="email" class="form-label d-block">Correo Electrónico</label>
|
iatoolkit/templates/base.html
CHANGED
|
@@ -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>
|
iatoolkit/templates/chat.html
CHANGED
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
<style>
|
|
8
8
|
{{ branding.css_variables | safe }}
|
|
9
9
|
</style>
|
|
10
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='css/onboarding.css', _external=True) }}">
|
|
11
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
12
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
10
13
|
|
|
11
14
|
<!-- Sección de encabezado con el usuario conectado -->
|
|
12
15
|
<div id="company-section" class="company-section d-flex justify-content-between align-items-center px-3 py-2"
|
|
@@ -49,6 +52,11 @@
|
|
|
49
52
|
class="ms-3 action-icon-style" title="Tu feedback es muy importante" style="color: {{ branding.header_text_color }};">
|
|
50
53
|
<i class="bi bi-emoji-smile"></i>
|
|
51
54
|
</a>
|
|
55
|
+
<a href="javascript:void(0);" id="onboarding-button"
|
|
56
|
+
class="ms-3 action-icon-style" title="Ver onboarding"
|
|
57
|
+
style="color: {{ branding.header_text_color }};">
|
|
58
|
+
<i class="bi bi-lightbulb"></i>
|
|
59
|
+
</a>
|
|
52
60
|
|
|
53
61
|
<!-- Icono de cerrar sesión (al final) -->
|
|
54
62
|
{% if user_is_local %}
|
|
@@ -174,20 +182,16 @@
|
|
|
174
182
|
window.iatoolkit_base_url = "{{ iatoolkit_base_url }}";
|
|
175
183
|
window.availablePrompts = {{ prompts.message | tojson }};
|
|
176
184
|
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 %}
|
|
185
|
+
window.onboardingCards = {{ onboarding_cards | tojson }};
|
|
182
186
|
</script>
|
|
183
187
|
|
|
184
188
|
<!-- Carga de los scripts JS externos después de definir las variables globales -->
|
|
189
|
+
<script src="{{ url_for('static', filename='js/chat_onboarding.js', _external=True) }}"></script>
|
|
185
190
|
<script src="{{ url_for('static', filename='js/chat_filepond.js', _external=True) }}"></script>
|
|
186
191
|
<script src="{{ url_for('static', filename='js/chat_history.js', _external=True) }}"></script>
|
|
187
192
|
<script src="{{ url_for('static', filename='js/chat_feedback.js', _external=True) }}"></script>
|
|
188
193
|
<script src="{{ url_for('static', filename='js/chat_main.js', _external=True) }}"></script>
|
|
189
194
|
|
|
190
|
-
|
|
191
195
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
|
|
192
196
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
|
193
197
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
|
@@ -274,5 +278,44 @@ document.addEventListener('DOMContentLoaded', function() {
|
|
|
274
278
|
});
|
|
275
279
|
});
|
|
276
280
|
});
|
|
281
|
+
|
|
282
|
+
// Inicialización del modal de onboarding
|
|
283
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
284
|
+
const btn = document.getElementById('onboarding-button');
|
|
285
|
+
if (!btn) return;
|
|
286
|
+
|
|
287
|
+
const modalEl = document.getElementById('onboardingModal');
|
|
288
|
+
const modal = new bootstrap.Modal(modalEl);
|
|
289
|
+
|
|
290
|
+
if (!window.initOnboarding) {
|
|
291
|
+
console.error('initOnboarding no disponible. Verifica chat_onboarding.js');
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const onboarding = initOnboarding({
|
|
296
|
+
mode: 'modal',
|
|
297
|
+
cards: Array.isArray(window.onboardingCards) ? window.onboardingCards : [],
|
|
298
|
+
ui: {
|
|
299
|
+
icon: '#ob-icon',
|
|
300
|
+
title: '#ob-title',
|
|
301
|
+
text: '#ob-text',
|
|
302
|
+
dots: '#ob-dots',
|
|
303
|
+
prev: '#ob-prev',
|
|
304
|
+
next: '#ob-next'
|
|
305
|
+
},
|
|
306
|
+
autoRotateMs: 5000
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
modalEl.addEventListener('hidden.bs.modal', () => onboarding.stop());
|
|
310
|
+
|
|
311
|
+
btn.addEventListener('click', () => {
|
|
312
|
+
if (!onboarding.hasCards()) {
|
|
313
|
+
toastr.info('No hay información de onboarding disponible.');
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
onboarding.start();
|
|
317
|
+
modal.show();
|
|
318
|
+
});
|
|
319
|
+
});
|
|
277
320
|
</script>
|
|
278
321
|
{% 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-secondary" data-bs-dismiss="modal">
|
|
140
|
+
Cerrar
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
112
145
|
</div>
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
|
|
73
73
|
// Actualizar action del formulario "Iniciar Sesión"
|
|
74
74
|
if (selectedCompany && selectedCompany.trim() !== '') {
|
|
75
|
-
const loginAction = '/' + selectedCompany + '/
|
|
75
|
+
const loginAction = '/' + selectedCompany + '/external_login';
|
|
76
76
|
$('#login-form').attr('action', loginAction); // Actualizamos la URL del form
|
|
77
77
|
} else {
|
|
78
78
|
$('#login-form').attr('action', '#'); // URL genérica si no hay selección
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
return;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
fetch(`/${selectedCompany}/
|
|
119
|
+
fetch(`/${selectedCompany}/external_login`, {
|
|
120
120
|
method: 'POST',
|
|
121
121
|
headers: {
|
|
122
122
|
'Content-Type': 'application/json',
|
|
@@ -1,167 +1,101 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
#card-container p { font-size: 0.95rem; color: #666; line-height: 1.5; min-height: 60px; }
|
|
54
|
-
.card-nav { display: flex; justify-content: space-between; align-items: center; margin-top: 20px; }
|
|
55
|
-
.card-nav button { background-color: var(--brand-secondary-color, #06326B); border: none; color: var(--brand-text-on-secondary, #FFFFFF); border-radius: 50%; width: 40px; height: 40px; cursor: pointer; transition: opacity 0.2s; }
|
|
56
|
-
.card-nav button:hover { opacity: 0.85; }
|
|
57
|
-
#progress-dots { display: flex; gap: 8px; }
|
|
58
|
-
.dot { width: 10px; height: 10px; border-radius: 50%; background-color: #ddd; transition: background-color 0.3s; }
|
|
59
|
-
.dot.active { background-color: var(--brand-primary-color, #FF5100); }
|
|
60
|
-
|
|
61
|
-
/* --- ESTILOS MEJORADOS: SPINNER DE CARGA --- */
|
|
62
|
-
#loading-status { margin-top: 30px; display: flex; align-items: center; gap: 15px; }
|
|
63
|
-
.spinner {
|
|
64
|
-
width: 30px; height: 30px; border: 4px solid rgba(0, 0, 0, 0.1);
|
|
65
|
-
border-top-color: var(--brand-primary-color, #FF5100);
|
|
66
|
-
border-radius: 50%;
|
|
67
|
-
animation: spin 1s linear infinite;
|
|
68
|
-
}
|
|
69
|
-
#loading-status p { font-size: 1rem; font-weight: 500; color: #555; margin: 0; }
|
|
70
|
-
@keyframes spin { to { transform: rotate(360deg); } }
|
|
71
|
-
|
|
72
|
-
/* --- Iframe (Sin cambios) --- */
|
|
73
|
-
#content-container { width: 100%; height: 100%; }
|
|
74
|
-
iframe { width: 100%; height: 100%; border: none; }
|
|
75
|
-
</style>
|
|
76
|
-
</head>
|
|
77
|
-
<body>
|
|
78
|
-
<div id="loader-wrapper">
|
|
79
|
-
|
|
80
|
-
<h1 id="brand-header">
|
|
81
|
-
<span class="brand-name">{{ branding.name | default('IAToolkit') }}</span> <span>IA</span>
|
|
82
|
-
</h1>
|
|
83
|
-
|
|
84
|
-
<div id="card-container">
|
|
85
|
-
<div id="card-icon" class="icon"><i class="fas fa-lightbulb"></i></div>
|
|
86
|
-
<h3 id="card-title">Título de la Tarjeta</h3>
|
|
87
|
-
<p id="card-text">Descripción de la tarjeta de capacitación.</p>
|
|
88
|
-
<div class="card-nav">
|
|
89
|
-
<button id="prev-card" aria-label="Anterior"><i class="fas fa-chevron-left"></i></button>
|
|
90
|
-
<div id="progress-dots"></div>
|
|
91
|
-
<button id="next-card" aria-label="Siguiente"><i class="fas fa-chevron-right"></i></button>
|
|
92
|
-
</div>
|
|
93
|
-
</div>
|
|
94
|
-
|
|
95
|
-
<!-- MEJORADO: Texto de estado ahora junto al spinner -->
|
|
96
|
-
<div id="loading-status">
|
|
97
|
-
<div class="spinner"></div>
|
|
98
|
-
<p>Inicializando el contexto de {{ branding.name }} para la IA...</p>
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Iniciando {{ branding.name | default('IAToolkit') }} IA...{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block styles %}
|
|
6
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='styles/llm_output.css', _external=True) }}?v=6">
|
|
7
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='css/onboarding.css', _external=True) }}?v=6">
|
|
8
|
+
<style>
|
|
9
|
+
.onboarding-shell-root { position: relative; height: 100vh; }
|
|
10
|
+
.onboarding-shell-root #loader-wrapper { position: absolute; inset: 0; background: #f4f7f6; z-index: 1000; display:flex; align-items:center; justify-content:center; padding:20px; box-sizing:border-box; transition: opacity .5s; }
|
|
11
|
+
.onboarding-shell-root .ob-stack { width:100%; max-width:520px; display:flex; flex-direction:column; gap:16px; }
|
|
12
|
+
.onboarding-shell-root .ob-loading-band { display:flex; align-items:center; justify-content:center; gap:12px; padding:12px 14px; background:#fff; border-radius:12px; box-shadow:0 4px 20px rgba(0,0,0,.08); }
|
|
13
|
+
.onboarding-shell-root .spinner { width:28px; height:28px; border:4px solid rgba(0,0,0,.1); border-top-color: var(--brand-primary-color, #FF5100); border-radius:50%; animation: spin 1s linear infinite; }
|
|
14
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
15
|
+
.onboarding-shell-root #content-container { width:100%; height:100%; }
|
|
16
|
+
.onboarding-shell-root #content-container iframe { width:100%; height:100%; border:none; }
|
|
17
|
+
|
|
18
|
+
/* Forzar colores de marca (sube especificidad y evita overrides) */
|
|
19
|
+
.onboarding-shell-root .ob-brand-header { color: var(--brand-secondary-color, #06326B) !important; }
|
|
20
|
+
.onboarding-shell-root .ob-brand-header .brand-name { color: var(--brand-primary-color, #FF5100) !important; }
|
|
21
|
+
.onboarding-shell-root .ob-icon { color: var(--brand-primary-color, #FF5100) !important; }
|
|
22
|
+
.onboarding-shell-root .ob-btn { background-color: var(--brand-secondary-color, #06326B) !important; color: var(--brand-text-on-secondary, #FFFFFF) !important; border:none !important; }
|
|
23
|
+
.onboarding-shell-root .ob-dots > div.active { background-color: var(--brand-primary-color, #FF5100) !important; }
|
|
24
|
+
</style>
|
|
25
|
+
{% if branding and branding.css_variables %}
|
|
26
|
+
<style>
|
|
27
|
+
{{ branding.css_variables|safe }}
|
|
28
|
+
</style>
|
|
29
|
+
{% endif %}
|
|
30
|
+
{% endblock %}
|
|
31
|
+
|
|
32
|
+
{% block content %}
|
|
33
|
+
<div class="onboarding-shell-root ob-root">
|
|
34
|
+
<div id="loader-wrapper">
|
|
35
|
+
<div class="ob-stack">
|
|
36
|
+
<h1 id="ob-brand-header" class="ob-brand-header">
|
|
37
|
+
<span class="brand-name text-brand-primary">{{ branding.name | default('IAToolkit') }}</span>
|
|
38
|
+
<span class="brand-rest"> IA</span>
|
|
39
|
+
</h1>
|
|
40
|
+
|
|
41
|
+
<div id="card-container" class="ob-card">
|
|
42
|
+
<div id="card-icon" class="ob-icon"><i class="fas fa-lightbulb"></i></div>
|
|
43
|
+
<h3 id="card-title" class="ob-title">Título de la Tarjeta</h3>
|
|
44
|
+
<p id="card-text" class="ob-text">Descripción de la tarjeta de capacitación.</p>
|
|
45
|
+
<div class="ob-nav">
|
|
46
|
+
<button id="prev-card" class="ob-btn btn-branded-primary" aria-label="Anterior">
|
|
47
|
+
<i class="fas fa-chevron-left"></i>
|
|
48
|
+
</button>
|
|
49
|
+
<div id="progress-dots" class="ob-dots"></div>
|
|
50
|
+
<button id="next-card" class="ob-btn btn-branded-primary" aria-label="Siguiente">
|
|
51
|
+
<i class="fas fa-chevron-right"></i>
|
|
52
|
+
</button>
|
|
99
53
|
</div>
|
|
54
|
+
</div>
|
|
100
55
|
|
|
56
|
+
<div id="loading-status" class="ob-loading-band">
|
|
57
|
+
<div class="spinner"></div>
|
|
58
|
+
<p>Inicializando el contexto de {{ branding.name }} para la IA...</p>
|
|
59
|
+
</div>
|
|
101
60
|
</div>
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const $loader = $('#loader-wrapper');
|
|
138
|
-
const $container = $('#content-container');
|
|
139
|
-
|
|
140
|
-
// URL para el iframe, pasada desde la vista InitiateExternalChatView
|
|
141
|
-
const iframeSrc = "{{ iframe_src_url }}";
|
|
142
|
-
|
|
143
|
-
// Creamos el elemento iframe
|
|
144
|
-
const iframe = document.createElement('iframe');
|
|
145
|
-
iframe.src = iframeSrc;
|
|
146
|
-
|
|
147
|
-
// Estilos para que ocupe toda la pantalla
|
|
148
|
-
iframe.style.width = '100%';
|
|
149
|
-
iframe.style.height = '100%';
|
|
150
|
-
iframe.style.border = 'none';
|
|
151
|
-
iframe.style.display = 'none'; // Empezamos oculto
|
|
152
|
-
|
|
153
|
-
// Evento que se dispara cuando el iframe ha terminado de cargar su contenido
|
|
154
|
-
iframe.onload = function() {
|
|
155
|
-
// Mostramos el iframe
|
|
156
|
-
iframe.style.display = 'block';
|
|
157
|
-
// Ocultamos la animación de carga con una transición suave
|
|
158
|
-
$loader.css('opacity', 0);
|
|
159
|
-
setTimeout(() => $loader.hide(), 500); // Lo eliminamos del DOM después de la transición
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
// Añadimos el iframe al contenedor en el DOM
|
|
163
|
-
$container.append(iframe);
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
<div id="content-container"></div>
|
|
64
|
+
</div>
|
|
65
|
+
{% endblock %}
|
|
66
|
+
|
|
67
|
+
{% block scripts %}
|
|
68
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
69
|
+
|
|
70
|
+
<script src="{{ url_for('static', filename='js/chat_onboarding.js', _external=True) }}"></script>
|
|
71
|
+
<script>
|
|
72
|
+
(function() {
|
|
73
|
+
const cardsData = {{ onboarding_cards | tojson }};
|
|
74
|
+
const iframeSrc = "{{ iframe_src_url }}";
|
|
75
|
+
|
|
76
|
+
if (!window.initOnboarding) {
|
|
77
|
+
console.error('initOnboarding no está disponible. Verifica la carga de chat_onboarding.js');
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const onboarding = initOnboarding({
|
|
82
|
+
mode: 'shell',
|
|
83
|
+
cards: cardsData,
|
|
84
|
+
ui: {
|
|
85
|
+
icon: '#card-icon',
|
|
86
|
+
title: '#card-title',
|
|
87
|
+
text: '#card-text',
|
|
88
|
+
dots: '#progress-dots',
|
|
89
|
+
prev: '#prev-card',
|
|
90
|
+
next: '#next-card',
|
|
91
|
+
loader: '#loader-wrapper',
|
|
92
|
+
container: '#content-container'
|
|
93
|
+
},
|
|
94
|
+
autoRotateMs: 5000,
|
|
95
|
+
shell: { iframeSrc: iframeSrc }
|
|
164
96
|
});
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
97
|
+
|
|
98
|
+
onboarding.start();
|
|
99
|
+
})();
|
|
100
|
+
</script>
|
|
101
|
+
{% endblock %}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# iatoolkit/views/base_login_view.py
|
|
2
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
3
|
+
# Product: IAToolkit
|
|
4
|
+
#
|
|
5
|
+
# IAToolkit is open source software.
|
|
6
|
+
|
|
7
|
+
from flask.views import MethodView
|
|
8
|
+
from flask import render_template, url_for
|
|
9
|
+
from injector import inject
|
|
10
|
+
from iatoolkit.services.profile_service import ProfileService
|
|
11
|
+
from iatoolkit.services.query_service import QueryService
|
|
12
|
+
from iatoolkit.services.branding_service import BrandingService
|
|
13
|
+
from iatoolkit.services.onboarding_service import OnboardingService
|
|
14
|
+
from iatoolkit.services.prompt_manager_service import PromptService
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseLoginView(MethodView):
|
|
18
|
+
"""
|
|
19
|
+
Base class for views that initiate a session and decide the context
|
|
20
|
+
loading path (fast or slow).
|
|
21
|
+
"""
|
|
22
|
+
@inject
|
|
23
|
+
def __init__(self,
|
|
24
|
+
profile_service: ProfileService,
|
|
25
|
+
branding_service: BrandingService,
|
|
26
|
+
prompt_service: PromptService,
|
|
27
|
+
onboarding_service: OnboardingService,
|
|
28
|
+
query_service: QueryService):
|
|
29
|
+
self.profile_service = profile_service
|
|
30
|
+
self.branding_service = branding_service
|
|
31
|
+
self.prompt_service = prompt_service
|
|
32
|
+
self.onboarding_service = onboarding_service
|
|
33
|
+
self.query_service = query_service
|
|
34
|
+
|
|
35
|
+
def _handle_login_path(self, company_short_name: str, user_identifier: str, company):
|
|
36
|
+
"""
|
|
37
|
+
Centralized logic to decide between the fast path and the slow path.
|
|
38
|
+
"""
|
|
39
|
+
# --- Get the company branding ---
|
|
40
|
+
branding_data = self.branding_service.get_company_branding(company)
|
|
41
|
+
|
|
42
|
+
# this service decides is the context needs to be rebuilt or not
|
|
43
|
+
prep_result = self.query_service.prepare_context(
|
|
44
|
+
company_short_name=company_short_name, user_identifier=user_identifier
|
|
45
|
+
)
|
|
46
|
+
if prep_result.get('rebuild_needed'):
|
|
47
|
+
# --- SLOW PATH: Render the loading shell ---
|
|
48
|
+
onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
|
|
49
|
+
|
|
50
|
+
# callback url to call when the context finish loading
|
|
51
|
+
target_url = url_for('finalize_context_load', company_short_name=company_short_name, _external=True)
|
|
52
|
+
|
|
53
|
+
return render_template(
|
|
54
|
+
"onboarding_shell.html",
|
|
55
|
+
iframe_src_url=target_url,
|
|
56
|
+
branding=branding_data,
|
|
57
|
+
onboarding_cards=onboarding_cards
|
|
58
|
+
)
|
|
59
|
+
else:
|
|
60
|
+
# --- FAST PATH: Render the chat page directly ---
|
|
61
|
+
prompts = self.prompt_service.get_user_prompts(company_short_name)
|
|
62
|
+
onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
|
|
63
|
+
return render_template(
|
|
64
|
+
"chat.html",
|
|
65
|
+
branding=branding_data,
|
|
66
|
+
prompts=prompts,
|
|
67
|
+
onboarding_cards=onboarding_cards
|
|
68
|
+
)
|
|
@@ -5,33 +5,41 @@
|
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
7
|
import logging
|
|
8
|
-
from flask import request, jsonify
|
|
9
|
-
from flask.views import MethodView
|
|
8
|
+
from flask import request, jsonify
|
|
10
9
|
from injector import inject
|
|
11
10
|
from iatoolkit.services.auth_service import AuthService
|
|
11
|
+
from iatoolkit.views.base_login_view import BaseLoginView
|
|
12
|
+
|
|
13
|
+
# Importar los servicios que necesita la clase base
|
|
12
14
|
from iatoolkit.services.profile_service import ProfileService
|
|
13
|
-
from iatoolkit.services.query_service import QueryService
|
|
14
|
-
from iatoolkit.services.prompt_manager_service import PromptService
|
|
15
15
|
from iatoolkit.services.branding_service import BrandingService
|
|
16
16
|
from iatoolkit.services.onboarding_service import OnboardingService
|
|
17
|
+
from iatoolkit.services.query_service import QueryService
|
|
18
|
+
from iatoolkit.services.prompt_manager_service import PromptService
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
class ExternalLoginView(BaseLoginView):
|
|
21
|
+
"""
|
|
22
|
+
Handles login for external users via API.
|
|
23
|
+
Authenticates and then delegates the path decision (fast/slow) to the base class.
|
|
24
|
+
"""
|
|
20
25
|
@inject
|
|
21
26
|
def __init__(self,
|
|
22
27
|
iauthentication: AuthService,
|
|
23
|
-
branding_service: BrandingService,
|
|
24
28
|
profile_service: ProfileService,
|
|
29
|
+
branding_service: BrandingService,
|
|
30
|
+
prompt_service: PromptService,
|
|
25
31
|
onboarding_service: OnboardingService,
|
|
26
|
-
query_service: QueryService
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
query_service: QueryService):
|
|
33
|
+
# Pass the dependencies for the base class to its __init__
|
|
34
|
+
super().__init__(
|
|
35
|
+
profile_service=profile_service,
|
|
36
|
+
branding_service=branding_service,
|
|
37
|
+
onboarding_service=onboarding_service,
|
|
38
|
+
query_service=query_service,
|
|
39
|
+
prompt_service=prompt_service
|
|
40
|
+
)
|
|
41
|
+
# Handle the dependency specific to this child class
|
|
29
42
|
self.iauthentication = iauthentication
|
|
30
|
-
self.branding_service = branding_service
|
|
31
|
-
self.profile_service = profile_service
|
|
32
|
-
self.onboarding_service = onboarding_service
|
|
33
|
-
self.query_service = query_service
|
|
34
|
-
self.prompt_service = prompt_service
|
|
35
43
|
|
|
36
44
|
def post(self, company_short_name: str):
|
|
37
45
|
data = request.get_json()
|
|
@@ -51,43 +59,12 @@ class InitiateExternalChatView(MethodView):
|
|
|
51
59
|
if not iaut.get("success"):
|
|
52
60
|
return jsonify(iaut), 401
|
|
53
61
|
|
|
54
|
-
# 2.
|
|
62
|
+
# 2. Create the external user session.
|
|
55
63
|
self.profile_service.create_external_user_session(company, external_user_id)
|
|
56
64
|
|
|
57
|
-
# 3.
|
|
58
|
-
|
|
59
|
-
company_short_name
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
branding_data = self.branding_service.get_company_branding(company)
|
|
64
|
-
onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
|
|
65
|
-
target_url = url_for('login', company_short_name=company_short_name,
|
|
66
|
-
_external=True)
|
|
67
|
-
|
|
68
|
-
return render_template(
|
|
69
|
-
"onboarding_shell.html",
|
|
70
|
-
iframe_src_url=target_url,
|
|
71
|
-
branding=branding_data,
|
|
72
|
-
onboarding_cards=onboarding_cards
|
|
73
|
-
)
|
|
74
|
-
else:
|
|
75
|
-
# fast path, the context is already on the cache, render the chat directly
|
|
76
|
-
try:
|
|
77
|
-
session_info = self.profile_service.get_current_session_info()
|
|
78
|
-
user_profile = session_info.get('profile', {})
|
|
79
|
-
|
|
80
|
-
prompts = self.prompt_service.get_user_prompts(company_short_name)
|
|
81
|
-
branding_data = self.branding_service.get_company_branding(company)
|
|
82
|
-
|
|
83
|
-
return render_template("chat.html",
|
|
84
|
-
company_short_name=company_short_name,
|
|
85
|
-
user_is_local=user_profile.get('user_is_local'),
|
|
86
|
-
user_email=user_profile.get('user_email'),
|
|
87
|
-
branding=branding_data,
|
|
88
|
-
prompts=prompts,
|
|
89
|
-
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
|
|
90
|
-
), 200
|
|
91
|
-
except Exception as e:
|
|
92
|
-
logging.exception(f"Error en el camino rápido para {company_short_name}/{external_user_id}: {e}")
|
|
93
|
-
return jsonify({"error": f"Error interno al iniciar el chat. {str(e)}"}), 500
|
|
65
|
+
# 3. Delegate the path decision to the centralized logic.
|
|
66
|
+
try:
|
|
67
|
+
return self._handle_login_path(company_short_name, external_user_id, company)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
logging.exception(f"Error processing external login path for {company_short_name}/{external_user_id}: {e}")
|
|
70
|
+
return jsonify({"error": f"Internal server error while starting chat. {str(e)}"}), 500
|
|
@@ -7,24 +7,39 @@ from flask.views import MethodView
|
|
|
7
7
|
from flask import render_template, request
|
|
8
8
|
from injector import inject
|
|
9
9
|
from iatoolkit.services.profile_service import ProfileService
|
|
10
|
+
from iatoolkit.services.branding_service import BrandingService
|
|
11
|
+
from iatoolkit.services.onboarding_service import OnboardingService
|
|
10
12
|
import os
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
class LoginTest(MethodView):
|
|
14
16
|
@inject
|
|
15
17
|
def __init__(self,
|
|
16
|
-
profile_service: ProfileService
|
|
18
|
+
profile_service: ProfileService,
|
|
19
|
+
branding_service: BrandingService,
|
|
20
|
+
onboarding_service: OnboardingService):
|
|
17
21
|
self.profile_service = profile_service
|
|
22
|
+
self.branding_service = branding_service
|
|
23
|
+
self.onboarding_service = onboarding_service
|
|
18
24
|
|
|
19
25
|
def get(self):
|
|
20
26
|
alert_message = request.args.get('alert_message', None)
|
|
21
27
|
companies = self.profile_service.get_companies()
|
|
28
|
+
branding_data = None
|
|
29
|
+
onboarding_cards = {}
|
|
30
|
+
if companies:
|
|
31
|
+
# Obtener el branding de la primera empresa para la página de prueba
|
|
32
|
+
first_company = companies[0]
|
|
33
|
+
branding_data = self.branding_service.get_company_branding(first_company)
|
|
34
|
+
onboarding_cards = self.onboarding_service.get_onboarding_cards(first_company)
|
|
22
35
|
|
|
23
36
|
# Esta API_KEY para el login
|
|
24
37
|
api_key_for_login = os.getenv("IATOOLKIT_API_KEY", "tu_api_key_por_defecto_o_error")
|
|
25
38
|
|
|
26
39
|
return render_template('login_test.html',
|
|
27
40
|
companies=companies,
|
|
41
|
+
branding=branding_data,
|
|
42
|
+
onboarding_cards=onboarding_cards,
|
|
28
43
|
alert_message=alert_message,
|
|
29
44
|
alert_icon='success' if alert_message else None,
|
|
30
45
|
api_key=api_key_for_login
|
iatoolkit/views/login_view.py
CHANGED
|
@@ -7,33 +7,19 @@ from flask.views import MethodView
|
|
|
7
7
|
from flask import request, redirect, render_template, url_for
|
|
8
8
|
from injector import inject
|
|
9
9
|
from iatoolkit.services.profile_service import ProfileService
|
|
10
|
-
from iatoolkit.services.prompt_manager_service import PromptService
|
|
11
10
|
from iatoolkit.services.query_service import QueryService
|
|
12
|
-
import
|
|
11
|
+
from iatoolkit.services.prompt_manager_service import PromptService
|
|
13
12
|
from iatoolkit.services.branding_service import BrandingService
|
|
14
13
|
from iatoolkit.services.onboarding_service import OnboardingService
|
|
14
|
+
from iatoolkit.views.base_login_view import BaseLoginView
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class
|
|
17
|
+
class LoginView(BaseLoginView):
|
|
18
18
|
"""
|
|
19
|
-
Handles
|
|
20
|
-
Authenticates
|
|
21
|
-
either the chat page directly or the loading shell.
|
|
19
|
+
Handles login for local users.
|
|
20
|
+
Authenticates and then delegates the path decision (fast/slow) to the base class.
|
|
22
21
|
"""
|
|
23
22
|
|
|
24
|
-
@inject
|
|
25
|
-
def __init__(self,
|
|
26
|
-
profile_service: ProfileService,
|
|
27
|
-
branding_service: BrandingService,
|
|
28
|
-
onboarding_service: OnboardingService,
|
|
29
|
-
query_service: QueryService,
|
|
30
|
-
prompt_service: PromptService):
|
|
31
|
-
self.profile_service = profile_service
|
|
32
|
-
self.branding_service = branding_service
|
|
33
|
-
self.onboarding_service = onboarding_service
|
|
34
|
-
self.query_service = query_service
|
|
35
|
-
self.prompt_service = prompt_service
|
|
36
|
-
|
|
37
23
|
def post(self, company_short_name: str):
|
|
38
24
|
company = self.profile_service.get_company_by_short_name(company_short_name)
|
|
39
25
|
if not company:
|
|
@@ -50,60 +36,31 @@ class InitiateLoginView(MethodView):
|
|
|
50
36
|
)
|
|
51
37
|
|
|
52
38
|
if not auth_response['success']:
|
|
39
|
+
branding_data = self.branding_service.get_company_branding(company)
|
|
40
|
+
|
|
53
41
|
return render_template(
|
|
54
42
|
'index.html',
|
|
55
43
|
company_short_name=company_short_name,
|
|
56
44
|
company=company,
|
|
45
|
+
branding=branding_data,
|
|
57
46
|
form_data={"email": email},
|
|
58
47
|
alert_message=auth_response["message"]
|
|
59
48
|
), 400
|
|
60
49
|
|
|
61
50
|
user_identifier = auth_response['user_identifier']
|
|
62
51
|
|
|
63
|
-
# 2.
|
|
64
|
-
|
|
65
|
-
company_short_name
|
|
66
|
-
|
|
52
|
+
# 2. Delegate the path decision to the centralized logic.
|
|
53
|
+
try:
|
|
54
|
+
return self._handle_login_path(company_short_name, user_identifier, company)
|
|
55
|
+
except Exception as e:
|
|
56
|
+
return render_template("error.html", company=company, company_short_name=company_short_name,
|
|
57
|
+
message=f"Error processing login path: {str(e)}"), 500
|
|
67
58
|
|
|
68
|
-
if prep_result.get('rebuild_needed'):
|
|
69
|
-
# --- SLOW PATH: Context rebuild is needed ---
|
|
70
|
-
# Render the shell, which will call LoginView for the heavy lifting.
|
|
71
|
-
branding_data = self.branding_service.get_company_branding(company)
|
|
72
|
-
onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
|
|
73
|
-
target_url = url_for('login', company_short_name=company_short_name, _external=True)
|
|
74
59
|
|
|
75
|
-
|
|
76
|
-
"onboarding_shell.html",
|
|
77
|
-
iframe_src_url=target_url,
|
|
78
|
-
branding=branding_data,
|
|
79
|
-
onboarding_cards=onboarding_cards
|
|
80
|
-
)
|
|
81
|
-
else:
|
|
82
|
-
# --- FAST PATH: Context is already cached ---
|
|
83
|
-
# Render chat.html directly.
|
|
84
|
-
try:
|
|
85
|
-
session_info = self.profile_service.get_current_session_info()
|
|
86
|
-
user_profile = session_info.get('profile', {})
|
|
87
|
-
|
|
88
|
-
prompts = self.prompt_service.get_user_prompts(company_short_name)
|
|
89
|
-
branding_data = self.branding_service.get_company_branding(company)
|
|
90
|
-
|
|
91
|
-
return render_template("chat.html",
|
|
92
|
-
user_is_local=user_profile.get('user_is_local'),
|
|
93
|
-
user_email=user_profile.get('user_email'),
|
|
94
|
-
branding=branding_data,
|
|
95
|
-
prompts=prompts,
|
|
96
|
-
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
|
|
97
|
-
), 200
|
|
98
|
-
except Exception as e:
|
|
99
|
-
return render_template("error.html", company=company, company_short_name=company_short_name,
|
|
100
|
-
message=f"Error in fast path: {str(e)}"), 500
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
class LoginView(MethodView):
|
|
60
|
+
class FinalizeContextView(MethodView):
|
|
104
61
|
"""
|
|
105
|
-
|
|
106
|
-
|
|
62
|
+
Finalizes context loading in the slow path.
|
|
63
|
+
This view is invoked by the iframe inside onboarding_shell.html.
|
|
107
64
|
"""
|
|
108
65
|
|
|
109
66
|
@inject
|
|
@@ -111,17 +68,19 @@ class LoginView(MethodView):
|
|
|
111
68
|
profile_service: ProfileService,
|
|
112
69
|
query_service: QueryService,
|
|
113
70
|
prompt_service: PromptService,
|
|
114
|
-
branding_service: BrandingService
|
|
71
|
+
branding_service: BrandingService,
|
|
72
|
+
onboarding_service: OnboardingService
|
|
73
|
+
):
|
|
115
74
|
self.profile_service = profile_service
|
|
116
75
|
self.query_service = query_service
|
|
117
76
|
self.prompt_service = prompt_service
|
|
118
77
|
self.branding_service = branding_service
|
|
78
|
+
self.onboarding_service = onboarding_service
|
|
119
79
|
|
|
120
80
|
def get(self, company_short_name: str):
|
|
121
|
-
# 1. Use the
|
|
81
|
+
# 1. Use the centralized method to get session info.
|
|
122
82
|
session_info = self.profile_service.get_current_session_info()
|
|
123
83
|
user_identifier = session_info.get('user_identifier')
|
|
124
|
-
user_profile = session_info.get('profile', {})
|
|
125
84
|
|
|
126
85
|
if not user_identifier:
|
|
127
86
|
# This can happen if the session expires or is invalid.
|
|
@@ -132,25 +91,23 @@ class LoginView(MethodView):
|
|
|
132
91
|
return render_template('error.html', message="Empresa no encontrada"), 404
|
|
133
92
|
|
|
134
93
|
try:
|
|
135
|
-
# 2. Finalize the context rebuild (the
|
|
136
|
-
# We pass the identifier, and the service resolves if it's local or external.
|
|
94
|
+
# 2. Finalize the context rebuild (the heavy task).
|
|
137
95
|
self.query_service.finalize_context_rebuild(
|
|
138
96
|
company_short_name=company_short_name,
|
|
139
97
|
user_identifier=user_identifier
|
|
140
98
|
)
|
|
141
99
|
|
|
142
|
-
# 3.
|
|
100
|
+
# 3. render the chat page.
|
|
143
101
|
prompts = self.prompt_service.get_user_prompts(company_short_name)
|
|
144
102
|
branding_data = self.branding_service.get_company_branding(company)
|
|
103
|
+
onboarding_cards = self.onboarding_service.get_onboarding_cards(company)
|
|
145
104
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
iatoolkit_base_url=os.getenv('IATOOLKIT_BASE_URL'),
|
|
153
|
-
), 200
|
|
105
|
+
return render_template(
|
|
106
|
+
"chat.html",
|
|
107
|
+
branding=branding_data,
|
|
108
|
+
prompts=prompts,
|
|
109
|
+
onboarding_cards=onboarding_cards
|
|
110
|
+
)
|
|
154
111
|
|
|
155
112
|
except Exception as e:
|
|
156
113
|
return render_template("error.html",
|
|
@@ -2,10 +2,10 @@ iatoolkit/__init__.py,sha256=4PWjMJjktixtrxF6BY405qyA50Sv967kEP2x-oil6qk,1120
|
|
|
2
2
|
iatoolkit/base_company.py,sha256=uFJmy77LPAceVqkTeuJqo15-auDiq4aTwvC_bbBD0mQ,4607
|
|
3
3
|
iatoolkit/cli_commands.py,sha256=G5L9xQXZ0lVFXQWBaE_KEZHyfuiT6PL1nTQRoSdnBzc,2302
|
|
4
4
|
iatoolkit/company_registry.py,sha256=tduqt3oV8iDX_IB1eA7KIgvIxE4edTcy-3qZIXh3Lzw,2549
|
|
5
|
-
iatoolkit/iatoolkit.py,sha256=
|
|
5
|
+
iatoolkit/iatoolkit.py,sha256=jIIhvxu1CwCiz3dLm9B7I2SzH-4sT0QQeci_XD2_C68,17305
|
|
6
6
|
iatoolkit/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
iatoolkit/common/exceptions.py,sha256=EXx40n5htp7UiOM6P1xfJ9U6NMcADqm62dlFaKz7ICU,1154
|
|
8
|
-
iatoolkit/common/routes.py,sha256=
|
|
8
|
+
iatoolkit/common/routes.py,sha256=Djf8Q_b5IGkdhQ5Az_AuYIVqam6-HFA2d4ByursdARI,6030
|
|
9
9
|
iatoolkit/common/session_manager.py,sha256=UeKfD15bcEA3P5e0WSURfotLqpsiIMp3AXxAMhtgHs0,471
|
|
10
10
|
iatoolkit/common/util.py,sha256=w9dTd3csK0gKtFSp-a4t7XmCPZiYDhiON92uXRbTT8A,14624
|
|
11
11
|
iatoolkit/infra/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
@@ -67,34 +67,37 @@ iatoolkit/static/js/chat_feedback.js,sha256=DDT2NPgglrLnW75vtEAVXS72MNt7vlMcavzr
|
|
|
67
67
|
iatoolkit/static/js/chat_filepond.js,sha256=mzXafm7a506EpM37KATTK3zvAswO1E0KSUY1vKbwuRc,3163
|
|
68
68
|
iatoolkit/static/js/chat_history.js,sha256=4hYNODIwYNd5vaQqkR28HZyXYIFKgSayrnmOuT_DUac,4381
|
|
69
69
|
iatoolkit/static/js/chat_main.js,sha256=j3rbJjWWCEAM1XUXPv6K2SW4S3kBrPAwEzVtLTjHslI,17314
|
|
70
|
-
iatoolkit/static/
|
|
70
|
+
iatoolkit/static/js/chat_onboarding.js,sha256=b6ofiFcPhuCaPmSFIvDQZqcMUVvbI7LpIsjZOZJUSAU,3185
|
|
71
|
+
iatoolkit/static/styles/chat_iatoolkit.css,sha256=aA-PZ2TGl_k82JSVVBC2-CJT0NiZAuLOGoiaJhdeVUU,11416
|
|
71
72
|
iatoolkit/static/styles/chat_info.css,sha256=17DbgoNYE21VYWfb5L9-QLCpD2R1idK4imKRLwXtJLY,1058
|
|
72
73
|
iatoolkit/static/styles/chat_modal.css,sha256=mdfjrJtmUn3O9rKwIGjJc-oSNmJGnzUY1aAJqEfPh38,4301
|
|
73
74
|
iatoolkit/static/styles/landing_page.css,sha256=5MHlXkmgZVv9uHE7rZTGYzZeynya3ONY4hp7e2uPXwk,4898
|
|
74
75
|
iatoolkit/static/styles/llm_output.css,sha256=AlxgRSOleeCk2dLAqFWVaQ-jwZiJjcpC5rHuUv3T6VU,2312
|
|
76
|
+
iatoolkit/static/styles/onboarding.css,sha256=Bo0hd8ngVy404_a-gtNFi-hzljhIAnpE-1oQJGnj0F0,3655
|
|
75
77
|
iatoolkit/system_prompts/format_styles.prompt,sha256=MSMe1qvR3cF_0IbFshn8R0z6Wx6VCHQq1p37rpu5wwk,3576
|
|
76
78
|
iatoolkit/system_prompts/query_main.prompt,sha256=D2Wjf0uunQIQsQiJVrY-BTQz6PemM5En6ftmw_c5t4E,2808
|
|
77
79
|
iatoolkit/system_prompts/sql_rules.prompt,sha256=y4nURVnb9AyFwt-lrbMNBHHtZlhk6kC9grYoOhRnrJo,59174
|
|
78
80
|
iatoolkit/templates/_branding_styles.html,sha256=x0GJmY1WWpPxKBUoqmxh685_1c6-4uLJWNPU6r81uAc,1912
|
|
79
|
-
iatoolkit/templates/_login_widget.html,sha256=
|
|
81
|
+
iatoolkit/templates/_login_widget.html,sha256=p7Xz0P1Xd3Otn41uVQTA3GmDswMrUVMIn9doDNJojAA,1852
|
|
80
82
|
iatoolkit/templates/_navbar.html,sha256=o1PvZE5ueLmVpGUAmsjtu-vS_WPROTlJc2sTXl6AS4Y,360
|
|
81
83
|
iatoolkit/templates/about.html,sha256=ciC08grUVz5qLzdzDDqDX31xirg5PrJIRYabWpV9oA8,294
|
|
82
|
-
iatoolkit/templates/base.html,sha256=
|
|
84
|
+
iatoolkit/templates/base.html,sha256=hHfBqZJsPcZGlb4BxAbHvpJFcSjckLIAVTYTmoyXrz0,2323
|
|
83
85
|
iatoolkit/templates/change_password.html,sha256=G5a3hYLTpz_5Q_eZ4LNcYSqLeW-CuT4NCHD8bkhAd9k,3573
|
|
84
|
-
iatoolkit/templates/chat.html,sha256=
|
|
85
|
-
iatoolkit/templates/chat_modals.html,sha256=
|
|
86
|
+
iatoolkit/templates/chat.html,sha256=spvypAVaVI1I22YRrYgQqzK1lXVPX5ywMp2MNixFTTY,13885
|
|
87
|
+
iatoolkit/templates/chat_modals.html,sha256=o3BmQBCTVun4ukyy-9E0e7FuBlgyVQKbRXuDn86SVnw,6949
|
|
86
88
|
iatoolkit/templates/error.html,sha256=c3dxieMygsvdjQMiQu_sn6kqqag9zFtVu-z5FunX6so,580
|
|
87
89
|
iatoolkit/templates/forgot_password.html,sha256=NRZqbNHJXSLNArF_KLbzuem-U57v07awS0ikI_DJbfM,2360
|
|
88
90
|
iatoolkit/templates/header.html,sha256=179agI7rnYwP_rvJNXIiVde5E8Ec5649_XKq6eew2Hk,1263
|
|
89
91
|
iatoolkit/templates/index.html,sha256=jBLCqZoIMmUCA1KQESW9BcEgaxE0Rjs-4-i2V0ueSMo,7654
|
|
90
|
-
iatoolkit/templates/login_test.html,sha256=
|
|
91
|
-
iatoolkit/templates/onboarding_shell.html,sha256=
|
|
92
|
+
iatoolkit/templates/login_test.html,sha256=HsLgRNowhrg-G7Cyv4MFEYc6m7dJ92OpnQP6ia6eKoM,5981
|
|
93
|
+
iatoolkit/templates/onboarding_shell.html,sha256=WA2-Or91epS2IeWf7m5vcuLYAjtpI36NBCtypcIiXAQ,4546
|
|
92
94
|
iatoolkit/templates/signup.html,sha256=9ArDvcNQgHFR2dwxy-37AXzGUOeOsT7Nz5u0y6fAB3U,4385
|
|
93
95
|
iatoolkit/templates/test.html,sha256=rwNtxC83tbCl5COZFXYvmRBxxmgFJtPNuVBd_nq9KWY,133
|
|
94
96
|
iatoolkit/views/__init__.py,sha256=5JqK9sZ6jBuK83zDQokUhxQ0wuJJJ9DXB8pYCLkX7X4,102
|
|
97
|
+
iatoolkit/views/base_login_view.py,sha256=6IWJXEg_6K9cPYoKnG_-Kpt_hIdYnv5ZNC5anIrytXk,2819
|
|
95
98
|
iatoolkit/views/change_password_view.py,sha256=tM0woZyKdhY4XYjS_YXg2sKq3RYkXGfcq_eVAKrNvNM,4498
|
|
96
99
|
iatoolkit/views/chat_token_request_view.py,sha256=wf32_A2Sq8NHYWshCwL10Tovd1znLoD0jQjzutR3sVE,4408
|
|
97
|
-
iatoolkit/views/external_login_view.py,sha256=
|
|
100
|
+
iatoolkit/views/external_login_view.py,sha256=qY5wxh98HyKI0Q1Phf6pkOzRGD7PvbH27GUZn0ccYu4,2889
|
|
98
101
|
iatoolkit/views/file_store_api_view.py,sha256=Uz9f6sey3_F5K8zuyQz6SwYRKAalCjD1ekf-Mkl_Kfo,2326
|
|
99
102
|
iatoolkit/views/forgot_password_view.py,sha256=-qKJeeOBqJFdvDUk7rCNg1E1cDQnJQkozPpb0T0FgwA,3159
|
|
100
103
|
iatoolkit/views/history_api_view.py,sha256=x-tZhB8UzqrD2n-WDIfmHK9iVhGZ9f0yncsGs9mxwt0,1953
|
|
@@ -102,15 +105,15 @@ iatoolkit/views/index_view.py,sha256=P5aVdEWxsYOZGbzcXd6WFE733qZ7YXIoeqriUMAM6V8
|
|
|
102
105
|
iatoolkit/views/init_context_api_view.py,sha256=1j8NKfODfPrffbA5YO8TPMHh-ildlLNzReIxv_qO-W4,2586
|
|
103
106
|
iatoolkit/views/llmquery_api_view.py,sha256=Rh-y-VENwwtNsDrYAD_SWKwjK16fW-pFRWlEvI-OYwY,2120
|
|
104
107
|
iatoolkit/views/llmquery_web_view.py,sha256=WhjlA1mfsoL8hL9tlKQfjCUcaTzT43odlp_uQKmT314,1500
|
|
105
|
-
iatoolkit/views/login_test_view.py,sha256=
|
|
106
|
-
iatoolkit/views/login_view.py,sha256=
|
|
108
|
+
iatoolkit/views/login_test_view.py,sha256=7bqj9XWYCNGZulwPCgBMlk3O1DEIje_A_Hqesa58CVU,1893
|
|
109
|
+
iatoolkit/views/login_view.py,sha256=eAsmiCWS2KSOq3czaxVGm3W9__yaXKxqB9SeuGsdnmI,4635
|
|
107
110
|
iatoolkit/views/prompt_api_view.py,sha256=MP0r-MiswwKcbNc_5KY7aVbHkrR218I8XCiCX1D0yTA,1244
|
|
108
111
|
iatoolkit/views/signup_view.py,sha256=BCjhM2lMiDPwYrlW_eEwPl-ZLupblbFfsonWtq0E4vU,3922
|
|
109
112
|
iatoolkit/views/tasks_review_view.py,sha256=keLsLCyOTTlcoIapnB_lbuSvLwrPVZVpBiFC_7ChbLg,3388
|
|
110
113
|
iatoolkit/views/tasks_view.py,sha256=a3anTXrJTTvbQuc6PSpOzidLKQFL4hWa7PI2Cppcz8w,4110
|
|
111
114
|
iatoolkit/views/user_feedback_api_view.py,sha256=59XB9uQLHI4Q6QA4_XhK787HzfXb-c6EY7k1Ccyr4hI,2424
|
|
112
115
|
iatoolkit/views/verify_user_view.py,sha256=7XLSaxvs8LjBr3cYOUDa9B8DqW_50IGlq0IvmOQcD0Y,2340
|
|
113
|
-
iatoolkit-0.
|
|
114
|
-
iatoolkit-0.
|
|
115
|
-
iatoolkit-0.
|
|
116
|
-
iatoolkit-0.
|
|
116
|
+
iatoolkit-0.55.0.dist-info/METADATA,sha256=thMCV6aAt67vKtHbdiK1zTVTTdW1Q-YC-SWgaSz3ywI,9301
|
|
117
|
+
iatoolkit-0.55.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
118
|
+
iatoolkit-0.55.0.dist-info/top_level.txt,sha256=V_w4QvDx0b1RXiy8zTCrD1Bp7AZkFe3_O0-9fMiwogg,10
|
|
119
|
+
iatoolkit-0.55.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|