v1.7.0: refactor max_bot to flat structure, add VCF+UserModel+NLP history context, portal pages and proxy fixes

- Refactored max_bot from nested packages to flat module structure
- Q2: Extended BotUser model (patronymic, email, org, address, vcf_raw, contact_hash, phone_verified, email_verified, last_interaction, total_conversations, total_tickets)
- Q2: VCF parser (FN, N, TEL, EMAIL, ORG, ADR), upsert on re-contact, NLP history context (_get_user_history_context -> YandexGPT)
- Q1: Broadcast preview modal with 10s confirmation timer
- Q3: CSS var(--white)->var(--bg-card), var(--text)->var(--text-primary)
- Q4: bot_settings showNotification(), editable max_bot_id
- Q5: Webhook secret passthrough via X-Max-Bot-Api-Secret
- Masking sensitive keys, dialog_cleared handler, migrate via _add_column_if_not_exists()
- Rate limit (asyncio.sleep 0.5 per 10), dead code removed, conv.intent context in contact.py
- Portal pages: bot_consent, bot_kb (edit), bot_settings, bot_test, bot_tickets, portal_settings
- Tests: 21/21 passing, added test_yandex_gpt.py, test_email_sender.py
- Deploy: deploy_full.sh, schema.sql, seed_knowledge_base.sql
This commit is contained in:
2026-05-29 02:30:30 +03:00
parent 493e0b37a1
commit 72b6879f4b
234 changed files with 26768 additions and 6240 deletions
+72
View File
@@ -52,8 +52,14 @@ img { max-width:100%; height:auto; }
align-items: center;
justify-content: center;
min-height: 100vh;
background: var(--bg-body);
}
[data-theme="dark"] .login-page {
background: linear-gradient(135deg, #0a0e1a 0%, #0d1a30 50%, #0a0e1a 100%);
}
[data-theme="light"] .login-page {
background: linear-gradient(135deg, #e8ecf1 0%, #f0f4f8 50%, #e8ecf1 100%);
}
.login-box {
background: var(--bg-card);
@@ -965,6 +971,72 @@ table .actions button {
color: var(--text-muted) !important;
}
/* ---------- ROLE SWITCHER ---------- */
.role-switcher {
position: relative;
}
.role-btn {
display: flex;
align-items: center;
gap: 4px;
background: var(--accent-dim);
border: 1px solid var(--border);
border-radius: 6px;
padding: 4px 10px;
cursor: pointer;
font-size: 12px;
color: var(--text-secondary);
transition: all 0.2s;
white-space: nowrap;
}
.role-btn:hover {
background: var(--accent);
color: #fff;
border-color: var(--accent);
}
.role-btn-label { font-weight: 600; text-transform: capitalize; }
.role-btn-arrow { font-size: 10px; }
.role-dropdown {
display: none;
position: absolute;
top: calc(100% + 4px);
right: 0;
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: 8px;
min-width: 160px;
box-shadow: var(--shadow);
z-index: 100;
overflow: hidden;
}
.role-dropdown.open { display: block; }
.role-dropdown-item {
display: block;
padding: 8px 14px;
font-size: 13px;
color: var(--text-primary);
text-decoration: none;
text-transform: capitalize;
transition: background 0.15s;
}
.role-dropdown-item:hover { background: var(--accent-dim); }
.role-dropdown-item.active { font-weight: 700; color: var(--accent); }
.role-dropdown-divider {
height: 1px;
background: var(--border);
margin: 4px 0;
}
.role-dropdown-reset { color: var(--danger); }
.role-dropdown-reset:hover { background: rgba(239,68,68,0.1) !important; }
/* ---------- USER NAME ---------- */
.navbar__user {
font-size: 13px;
color: var(--text-secondary);
font-weight: 500;
white-space: nowrap;
}
/* ---------- DOCUMENTS ---------- */
.container {
max-width: 1200px;