mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-05 09:14:58 +03:00
✨ feat(settings): у каждого подключения ссылка на статью справки
Токен бота, ключ доступа сообщества, пароль ящика — всё это выдаёт не наша система, и человек уходит искать инструкцию в поиске, хотя она написана и лежит в Центре помощи. Теперь под выбором типа стоит ссылка на статью именно про этот тип: Telegram, MAX, ВКонтакте, почтовый ящик, веб-виджет. Адрес Центра помощи один на продукт — это документация Chatballs, а не портал организации, поэтому он лежит константой в shared/help и от установки не зависит. Статья у типа подключения необязательна: у LLM-провайдеров ссылки пока нет, и форма просто её не рисует. Ссылка оформлена общим классом `.link` в роли второстепенной и стоит подписью к полю «Тип» — своего стиля у неё нет. Проверено: tsc, тесты каталога переводов и модели подключений, вид формы на изолированном макете со штатными стилями. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
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;
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Проверить",
|
||||
|
||||
@@ -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}`;
|
||||
}
|
||||
Reference in new issue
Block a user