✨ feat(settings): у каждого подключения ссылка на статью справки

Токен бота, ключ доступа сообщества, пароль ящика — всё это выдаёт не наша
система, и человек уходит искать инструкцию в поиске, хотя она написана и
лежит в Центре помощи. Теперь под выбором типа стоит ссылка на статью
именно про этот тип: Telegram, MAX, ВКонтакте, почтовый ящик, веб-виджет.

Адрес Центра помощи один на продукт — это документация Chatballs, а не
портал организации, поэтому он лежит константой в shared/help и от
установки не зависит. Статья у типа подключения необязательна: у
LLM-провайдеров ссылки пока нет, и форма просто её не рисует.

Ссылка оформлена общим классом `.link` в роли второстепенной и стоит
подписью к полю «Тип» — своего стиля у неё нет.

Проверено: tsc, тесты каталога переводов и модели подключений, вид формы
на изолированном макете со штатными стилями.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
AndreyandClaude Opus 5 committed 2026-09-17 11:02:20 +03:00
1 parent 31985fc35c
commit eb98b9b781
6 files changed
+36 -5

No files matched your search

@@ -2,6 +2,7 @@ import { Modal } from "antd";
import { useEffect, useState } from "react";
import { api } from "../../api/client";
import { helpArticleUrl } from "../../shared/help";
import { Icon } from "../../shared/icons";
import { FormField, SelectField } from "../../shared/form-controls";
import { Button } from "../../shared/ui-controls";
@@ -124,6 +125,12 @@ export function IntegrationForm({ initial, kind, onClose, onSaved }: { initial:
) : (
<SelectField label={t("settings.type")} value={provider} onChange={(value) => setProvider(value as IntegrationProvider)} options={options} />
)}
{meta.helpSlug && (
<a className="link is-muted has-icon integration-form-help" href={helpArticleUrl(meta.helpSlug)} target="_blank" rel="noopener noreferrer">
{t("settings.how_to_connect")}
<Icon name="external" size={13} strokeWidth={2.2} />
</a>
)}
<FormField label={t("common.title")} value={name} onChange={setName} placeholder={isEmail ? t("settings.e_g_support_mailbox") : t("settings.e_g_openrouter_primary")} />
{isEmail && <EmailFields value={emailConfig} onChange={setEmailConfig} />}
{meta.testable && (
@@ -67,6 +67,8 @@ type ProviderMeta = {
// (у Web-виджета секрета нет, но backend проверяет привязку к каналу).
testable: boolean;
checkable: boolean;
// Статья Центра помощи про этот тип подключения (shared/help).
helpSlug?: string;
};
export const PROVIDERS: Record<IntegrationProvider, ProviderMeta> = {
@@ -76,14 +78,14 @@ export const PROVIDERS: Record<IntegrationProvider, ProviderMeta> = {
CUSTOM: { label: "Custom (OpenAI-compatible)", kind: "LLM_PROVIDER", secretLabel: t("settings.api_key"), defaultBaseUrl: "", hasModel: true, testable: true, checkable: true },
// Демо-провайдер — живой AI без ключей и сети для знакомства с системой: отвечает по знаниям агента.
DEMO: { label: t("settings.demo_provider_no_key"), kind: "LLM_PROVIDER", secretLabel: "", defaultBaseUrl: "", hasModel: false, testable: false, checkable: true },
MAX: { label: "MAX", kind: "MESSENGER", secretLabel: t("settings.bot_token"), defaultBaseUrl: "https://platform-api.max.ru", hasModel: false, testable: true, checkable: true },
TELEGRAM: { label: "Telegram", kind: "MESSENGER", secretLabel: t("settings.bot_token"), defaultBaseUrl: "https://api.telegram.org", hasModel: false, testable: true, checkable: true },
MAX: { label: "MAX", kind: "MESSENGER", secretLabel: t("settings.bot_token"), defaultBaseUrl: "https://platform-api.max.ru", hasModel: false, testable: true, checkable: true, helpSlug: "max" },
TELEGRAM: { label: "Telegram", kind: "MESSENGER", secretLabel: t("settings.bot_token"), defaultBaseUrl: "https://api.telegram.org", hasModel: false, testable: true, checkable: true, helpSlug: "telegram" },
// ВКонтакте — сообщество: секрет это ключ доступа сообщества, идентификатор
// сообщества подставляет проверка подключения (ADR-CHATBALLS-0020).
VK: { label: "ВКонтакте", kind: "MESSENGER", secretLabel: t("settings.vk_community_key"), defaultBaseUrl: "https://api.vk.com/method", hasModel: false, testable: true, checkable: true },
WEB: { label: t("common.web_widget"), kind: "MESSENGER", secretLabel: "", defaultBaseUrl: "", hasModel: false, testable: false, checkable: true },
VK: { label: "ВКонтакте", kind: "MESSENGER", secretLabel: t("settings.vk_community_key"), defaultBaseUrl: "https://api.vk.com/method", hasModel: false, testable: true, checkable: true, helpSlug: "vkontakte" },
WEB: { label: t("common.web_widget"), kind: "MESSENGER", secretLabel: "", defaultBaseUrl: "", hasModel: false, testable: false, checkable: true, helpSlug: "veb-vidzhet" },
// Email — подключение-ящик IMAP/SMTP (ADR-CHATBALLS-0035); секрет — пароль приложения.
EMAIL: { label: "Email (IMAP/SMTP)", kind: "MESSENGER", secretLabel: t("common.password"), defaultBaseUrl: "", hasModel: false, testable: true, checkable: true },
EMAIL: { label: "Email (IMAP/SMTP)", kind: "MESSENGER", secretLabel: t("common.password"), defaultBaseUrl: "", hasModel: false, testable: true, checkable: true, helpSlug: "pochtovyj-yashchik" },
};
export const STATUS_META: Record<IntegrationStatus, { label: string; bg: string; color: string }> = {
@@ -138,6 +138,14 @@
font-size: 11.5px;
}
/* Ссылка на статью Центра помощи про выбранный тип подключения: стоит под
полем «Тип» подписью к нему, поэтому подтянута к нему вплотную. */
.integration-form-help {
align-self: flex-start;
margin-top: -10px;
font-size: 12.5px;
}
/* Секции Email-формы: IMAP / SMTP (SPEC-CHATBALLS-0025 §3.2). */
.integration-email-section {
display: flex;
+1
View File
@@ -1482,6 +1482,7 @@ export const en: Record<MessageKey, Message> = {
"settings.bot": "Bot",
"settings.bot_token": "Bot token",
"settings.vk_community_key": "Community access key",
"settings.how_to_connect": "How to connect",
"settings.bots_email_web_widget_entry": "Bots, email and the web widget are the entry points for conversations. Each is bound to the agent that answers first.",
"settings.bucket": "Bucket",
"settings.check": "Check",
+1
View File
@@ -1483,6 +1483,7 @@ export const ru = {
"settings.bot": "Бот",
"settings.bot_token": "Токен бота",
"settings.vk_community_key": "Ключ доступа сообщества",
"settings.how_to_connect": "Как подключить",
"settings.bots_email_web_widget_entry": "Боты, почта и Web-виджет — точки входа диалогов. Каждая привязана к агенту, который отвечает первым.",
"settings.bucket": "Бакет",
"settings.check": "Проверить",
+12
View File
@@ -0,0 +1,12 @@
/* Ссылки на Центр помощи продукта.
Центр помощи один на продукт и живёт на домене разработчика: это
документация Chatballs, а не портал организации, поэтому адрес здесь
постоянный и от установки не зависит. Порталы самой организации
настраиваются в разделе «Порталы» и к этим ссылкам отношения не имеют. */
const HELP_CENTER_URL = "https://chatballs.com.edevs.tech";
export function helpArticleUrl(slug: string): string {
return `${HELP_CENTER_URL}/articles/${slug}`;
}