diff --git a/web/lib/opal/src/icons/file-text.tsx b/web/lib/opal/src/icons/file-text.tsx index f79243e23b..778b14cec8 100644 --- a/web/lib/opal/src/icons/file-text.tsx +++ b/web/lib/opal/src/icons/file-text.tsx @@ -1,17 +1,16 @@ import type { IconProps } from "@opal/types"; - const SvgFileText = ({ size, ...props }: IconProps) => ( ( ( > - - - - - ); export default SvgGlobe; diff --git a/web/lib/opal/src/layouts/content-action/styles.css b/web/lib/opal/src/layouts/content-action/styles.css index 1bf29c08fd..362edbe3eb 100644 --- a/web/lib/opal/src/layouts/content-action/styles.css +++ b/web/lib/opal/src/layouts/content-action/styles.css @@ -1,7 +1,7 @@ @reference "#reference.css"; .opal-content-action { - @apply flex flex-row w-full gap-4 items-stretch; + @apply flex flex-row w-full items-stretch gap-0; } .opal-content-action[data-centered="true"] { diff --git a/web/next.config.js b/web/next.config.js index 6f9d1e8ebe..cf09a31aef 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -209,6 +209,13 @@ const nextConfig = { destination: "/admin/web-search", permanent: true, }, + // The connector catalog moved from /admin/add-connector to + // /admin/connectors, beside the per-source wizard at /admin/connectors/:source. + { + source: "/admin/add-connector", + destination: "/admin/connectors", + permanent: true, + }, // Replaces the redirect page that used to live at // /admin/configuration/craft, kept for /admin/craft/access bookmarks. { diff --git a/web/src/app/admin/connectors/page.tsx b/web/src/app/admin/connectors/page.tsx new file mode 100644 index 0000000000..6ca7ba99f4 --- /dev/null +++ b/web/src/app/admin/connectors/page.tsx @@ -0,0 +1 @@ +export { default } from "@/views/admin/ConnectorsPage"; diff --git a/web/src/app/admin/indexing/status/page.tsx b/web/src/app/admin/indexing/status/page.tsx index 8bf737355c..6e68273ba7 100644 --- a/web/src/app/admin/indexing/status/page.tsx +++ b/web/src/app/admin/indexing/status/page.tsx @@ -223,7 +223,7 @@ export default function Status() { icon={route.icon} title={adminRouteTitle(route)} rightChildren={ - موصل موحّد مهيأ بالفعل. انقر لتعديل الموصل الحالي.", "slackCredentialsFound": "تم العثور على بيانات اعتماد Slack موجودة. انقر لإدارة موصل Slack الخاص بك." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "ربط {source}" + } + }, + "sources": { + "web": { + "description": "ربط أي عنوان URL عام" + }, + "github": { + "description": "الكود وطلبات السحب" + }, + "gitlab": { + "description": "الكود و CI/CD" + }, + "slack": { + "description": "مراسلة الفريق" + }, + "googleDrive": { + "description": "الملفات والمجلدات المشتركة" + }, + "gmail": { + "description": "بريد Google" + }, + "bookstack": { + "description": "ويكي مستضاف ذاتيًا" + }, + "outline": { + "description": "ويكي فريق مفتوح المصدر" + }, + "confluence": { + "description": "ويكي Atlassian" + }, + "jira": { + "description": "متتبع مشكلات Atlassian" + }, + "productboard": { + "description": "إدارة المنتجات" + }, + "slab": { + "description": "ويكي الفريق" + }, + "coda": { + "description": "المستندات وقواعد البيانات" + }, + "notion": { + "description": "المستندات وقواعد البيانات" + }, + "guru": { + "description": "قاعدة معرفة موثّقة" + }, + "gong": { + "description": "تحليل مكالمات المبيعات" + }, + "zulip": { + "description": "مراسلة مفتوحة المصدر" + }, + "linear": { + "description": "متتبع مشكلات الهندسة" + }, + "hubspot": { + "description": "التسويق وإدارة علاقات العملاء" + }, + "document360": { + "description": "وثائق الخدمة الذاتية" + }, + "file": { + "description": "رفع من الملفات المحلية" + }, + "userFile": { + "description": "الملفات المرفوعة في الدردشة" + }, + "googleSites": { + "description": "صفحات مستضافة على Google" + }, + "loopio": { + "description": "الرد على طلبات العروض" + }, + "box": { + "description": "الملفات والمجلدات والملاحظات" + }, + "dropbox": { + "description": "الملفات والمجلدات المشتركة" + }, + "discord": { + "description": "مراسلة المجتمع" + }, + "salesforce": { + "description": "المبيعات وإدارة علاقات العملاء" + }, + "sharepoint": { + "description": "شبكة Microsoft الداخلية" + }, + "teams": { + "description": "دردشات فرق Microsoft" + }, + "outlook": { + "description": "رسائل البريد ومجلداته" + }, + "zendesk": { + "description": "تذاكر دعم العملاء" + }, + "discourse": { + "description": "منتدى المجتمع" + }, + "axero": { + "description": "شبكة داخلية اجتماعية" + }, + "clickup": { + "description": "متتبع المشاريع والمهام" + }, + "wikipedia": { + "description": "قاعدة معرفة عامة" + }, + "mediawiki": { + "description": "ويكي بنمط ويكيبيديا" + }, + "asana": { + "description": "إدارة العمل" + }, + "s3": { + "description": "حاويات تخزين AWS" + }, + "r2": { + "description": "حاويات التخزين السحابي" + }, + "googleCloudStorage": { + "description": "حاويات Google Cloud" + }, + "xenforo": { + "description": "منتدى المجتمع" + }, + "ociStorage": { + "description": "تخزين كائنات OCI" + }, + "notApplicable": { + "description": "لا يوجد مصدر" + }, + "ingestionApi": { + "description": "المستندات المرسلة عبر واجهة البرمجة" + }, + "freshdesk": { + "description": "مكتب مساعدة العملاء" + }, + "fireflies": { + "description": "ملاحظات الاجتماعات" + }, + "egnyte": { + "description": "خدمات ملفات مُدارة" + }, + "airtable": { + "description": "قاعدة بيانات ومهام" + }, + "gitbook": { + "description": "وثائق المطورين" + }, + "highspot": { + "description": "تمكين المبيعات" + }, + "drupalWiki": { + "description": "ويكي قائم على نظام إدارة محتوى" + }, + "imap": { + "description": "مصدر بريد IMAP" + }, + "bitbucket": { + "description": "إدارة الشيفرة من Atlassian" + }, + "testrail": { + "description": "تتبع حالات الاختبار" + }, + "braintrust": { + "description": "السجلات والتقييمات" + }, + "lumapps": { + "description": "صفحات الشبكة الداخلية والمجتمعات" + }, + "canvas": { + "description": "الدورات والصفحات والإعلانات" + }, + "craftFile": { + "description": "الملفات التي رفعتها" + }, + "federatedSlack": { + "description": "البحث في Slack عند الاستعلام" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "تم إنشاء الموصل بنجاح" }, "empty": { - "message": "يبدو أنه ليس لديك أي موصلات معدّة بعد. زر صفحة [إضافة موصل](/admin/add-connector) للبدء!" + "message": "يبدو أنه ليس لديك أي موصلات معدّة بعد. زر صفحة [إضافة موصل](/admin/connectors) للبدء!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "إضافة موصل" + "connectors": { + "label": "الموصلات" }, "agents": { "label": "الوكلاء" diff --git a/web/src/i18n/messages/de.json b/web/src/i18n/messages/de.json index 3d6b446bfc..378754d3c7 100644 --- a/web/src/i18n/messages/de.json +++ b/web/src/i18n/messages/de.json @@ -779,41 +779,229 @@ "addConnector": { "categories": { "codeRepository": { - "label": "Code-Repository" + "label": "Code-Repositories" }, "messaging": { "label": "Messaging" }, - "other": { - "label": "Sonstige" - }, "sales": { - "label": "Vertrieb" + "label": "Vertrieb & GTM" }, "storage": { "label": "Cloud-Speicher" }, "ticketingAndTaskManagement": { - "label": "Ticketing & Aufgabenverwaltung" + "label": "Tickets & Aufgaben" }, "wiki": { "label": "Wissensbasis & Wikis" + }, + "aiObservability": { + "label": "KI & Observability" + }, + "other": { + "label": "Sonstige" } }, "popular": { - "title": "Beliebt" + "title": "Connector hinzufügen", + "description": "Verbinden Sie {appName} mit Ihren Datenquellen." }, "search": { - "placeholder": "Konnektoren suchen" - }, - "seeConnectorsButton": { - "label": "Konnektoren anzeigen" + "placeholder": "Konnektoren suchen..." }, "sourceTile": { "tooltip": { "federatedConfigured": "Föderierter Konnektor bereits konfiguriert. Klicken Sie, um den vorhandenen Konnektor zu bearbeiten.", "slackCredentialsFound": "Vorhandene Slack-Anmeldedaten gefunden. Klicken Sie, um Ihren Slack-Konnektor zu verwalten." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "{source} verbinden" + } + }, + "sources": { + "web": { + "description": "Beliebige öffentliche URL verknüpfen" + }, + "github": { + "description": "Code & Pull Requests" + }, + "gitlab": { + "description": "Code & CI/CD" + }, + "slack": { + "description": "Team-Messaging" + }, + "googleDrive": { + "description": "Geteilte Dateien und Ordner" + }, + "gmail": { + "description": "Google-E-Mail" + }, + "bookstack": { + "description": "Selbst gehostetes Wiki" + }, + "outline": { + "description": "Open-Source-Team-Wiki" + }, + "confluence": { + "description": "Atlassian-Wiki" + }, + "jira": { + "description": "Atlassian-Issue-Tracker" + }, + "productboard": { + "description": "Produktmanagement" + }, + "slab": { + "description": "Team-Wiki" + }, + "coda": { + "description": "Dokumente & Datenbanken" + }, + "notion": { + "description": "Dokumente & Datenbanken" + }, + "guru": { + "description": "Verifizierte Wissensdatenbank" + }, + "gong": { + "description": "Sales-Call-Intelligence" + }, + "zulip": { + "description": "Open-Source-Messaging" + }, + "linear": { + "description": "Engineering-Issue-Tracker" + }, + "hubspot": { + "description": "Marketing & CRM" + }, + "document360": { + "description": "Self-Service-Dokumentation" + }, + "file": { + "description": "Aus lokalen Dateien hochladen" + }, + "userFile": { + "description": "Im Chat hochgeladene Dateien" + }, + "googleSites": { + "description": "Von Google gehostete Seiten" + }, + "loopio": { + "description": "RFP-Antworten" + }, + "box": { + "description": "Dateien, Ordner und Notizen" + }, + "dropbox": { + "description": "Geteilte Dateien und Ordner" + }, + "discord": { + "description": "Community-Messaging" + }, + "salesforce": { + "description": "Vertrieb & CRM" + }, + "sharepoint": { + "description": "Microsoft-Intranet" + }, + "teams": { + "description": "Microsoft-Team-Chats" + }, + "outlook": { + "description": "E-Mails und Postfachordner" + }, + "zendesk": { + "description": "Kundensupport-Tickets" + }, + "discourse": { + "description": "Community-Forum" + }, + "axero": { + "description": "Soziales Intranet" + }, + "clickup": { + "description": "Projekt- & Aufgaben-Tracker" + }, + "wikipedia": { + "description": "Öffentliche Wissensdatenbank" + }, + "mediawiki": { + "description": "Wiki im Wikipedia-Stil" + }, + "asana": { + "description": "Arbeitsmanagement" + }, + "s3": { + "description": "AWS-Storage-Buckets" + }, + "r2": { + "description": "Cloud-Storage-Buckets" + }, + "googleCloudStorage": { + "description": "Google-Cloud-Buckets" + }, + "xenforo": { + "description": "Community-Forum" + }, + "ociStorage": { + "description": "OCI Object Storage" + }, + "notApplicable": { + "description": "Keine Quelle" + }, + "ingestionApi": { + "description": "Über die API gesendete Dokumente" + }, + "freshdesk": { + "description": "Kunden-Helpdesk" + }, + "fireflies": { + "description": "Meeting-Notizen" + }, + "egnyte": { + "description": "Verwaltete Dateidienste" + }, + "airtable": { + "description": "Datenbank & Aufgaben" + }, + "gitbook": { + "description": "Entwicklerdokumentation" + }, + "highspot": { + "description": "Sales Enablement" + }, + "drupalWiki": { + "description": "CMS-basiertes Wiki" + }, + "imap": { + "description": "IMAP-E-Mail-Quelle" + }, + "bitbucket": { + "description": "Atlassian-Quellcodeverwaltung" + }, + "testrail": { + "description": "Testfall-Verwaltung" + }, + "braintrust": { + "description": "Logs und Auswertungen" + }, + "lumapps": { + "description": "Intranet-Seiten und Communities" + }, + "canvas": { + "description": "Kurse, Seiten und Ankündigungen" + }, + "craftFile": { + "description": "Von Ihnen hochgeladene Dateien" + }, + "federatedSlack": { + "description": "Slack zur Abfragezeit durchsuchen" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "Konnektor erfolgreich erstellt" }, "empty": { - "message": "Sie haben anscheinend noch keine Konnektoren eingerichtet. Öffnen Sie die Seite [Konnektor hinzufügen](/admin/add-connector), um zu beginnen!" + "message": "Sie haben anscheinend noch keine Konnektoren eingerichtet. Öffnen Sie die Seite [Konnektor hinzufügen](/admin/connectors), um zu beginnen!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "Konnektor hinzufügen" + "connectors": { + "label": "Konnektoren" }, "agents": { "label": "Agenten" diff --git a/web/src/i18n/messages/en.json b/web/src/i18n/messages/en.json index a3bcab3a50..48bf04a697 100644 --- a/web/src/i18n/messages/en.json +++ b/web/src/i18n/messages/en.json @@ -779,41 +779,229 @@ "addConnector": { "categories": { "codeRepository": { - "label": "Code Repository" + "label": "Code Repositories" }, "messaging": { "label": "Messaging" }, - "other": { - "label": "Others" - }, "sales": { - "label": "Sales" + "label": "Sales & GTM" }, "storage": { "label": "Cloud Storage" }, "ticketingAndTaskManagement": { - "label": "Ticketing & Task Management" + "label": "Ticketing & Tasks" }, "wiki": { "label": "Knowledge Base & Wikis" + }, + "aiObservability": { + "label": "AI & Observability" + }, + "other": { + "label": "Other" } }, "popular": { - "title": "Popular" + "title": "Add Connector", + "description": "Connect {appName} to your data sources." }, "search": { - "placeholder": "Search Connectors" - }, - "seeConnectorsButton": { - "label": "See Connectors" + "placeholder": "Search connectors..." }, "sourceTile": { "tooltip": { "federatedConfigured": "Federated connector already configured. Click to edit the existing connector.", "slackCredentialsFound": "Existing Slack credentials found. Click to manage your Slack connector." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "Connect {source}" + } + }, + "sources": { + "web": { + "description": "Link any public URL" + }, + "github": { + "description": "Code & pull requests" + }, + "gitlab": { + "description": "Code & CI/CD" + }, + "slack": { + "description": "Team messaging" + }, + "googleDrive": { + "description": "Shared files & folders" + }, + "gmail": { + "description": "Google email" + }, + "bookstack": { + "description": "Self-hosted wiki" + }, + "outline": { + "description": "Open-source team wiki" + }, + "confluence": { + "description": "Atlassian wiki" + }, + "jira": { + "description": "Atlassian issue tracker" + }, + "productboard": { + "description": "Product management" + }, + "slab": { + "description": "Team wiki" + }, + "coda": { + "description": "Docs & databases" + }, + "notion": { + "description": "Docs & databases" + }, + "guru": { + "description": "Verified knowledge base" + }, + "gong": { + "description": "Sales call intelligence" + }, + "zulip": { + "description": "Open-source messaging" + }, + "linear": { + "description": "Engineering issue tracker" + }, + "hubspot": { + "description": "Marketing & CRM" + }, + "document360": { + "description": "Self-service docs" + }, + "file": { + "description": "Upload from local files" + }, + "userFile": { + "description": "Files uploaded in chat" + }, + "googleSites": { + "description": "Google-hosted pages" + }, + "loopio": { + "description": "RFP response" + }, + "box": { + "description": "Files, folders, & notes" + }, + "dropbox": { + "description": "Shared files and folders" + }, + "discord": { + "description": "Community messaging" + }, + "salesforce": { + "description": "Sales & CRM" + }, + "sharepoint": { + "description": "Microsoft intranet" + }, + "teams": { + "description": "Microsoft team chats" + }, + "outlook": { + "description": "Emails & mail folders" + }, + "zendesk": { + "description": "Customer support tickets" + }, + "discourse": { + "description": "Community forum" + }, + "axero": { + "description": "Social intranet" + }, + "clickup": { + "description": "Project & task tracker" + }, + "wikipedia": { + "description": "Public knowledge base" + }, + "mediawiki": { + "description": "Wikipedia-style wiki" + }, + "asana": { + "description": "Work management" + }, + "s3": { + "description": "AWS storage buckets" + }, + "r2": { + "description": "Cloud storage buckets" + }, + "googleCloudStorage": { + "description": "Google cloud buckets" + }, + "xenforo": { + "description": "Community forum" + }, + "ociStorage": { + "description": "OCI object storage" + }, + "notApplicable": { + "description": "No source" + }, + "ingestionApi": { + "description": "Documents sent through the API" + }, + "freshdesk": { + "description": "Customer helpdesk" + }, + "fireflies": { + "description": "Meeting notes" + }, + "egnyte": { + "description": "Managed file services" + }, + "airtable": { + "description": "Database & tasks" + }, + "gitbook": { + "description": "Developer docs" + }, + "highspot": { + "description": "Sales enablement" + }, + "drupalWiki": { + "description": "CMS-based wiki" + }, + "imap": { + "description": "IMAP email source" + }, + "bitbucket": { + "description": "Atlassian source control" + }, + "testrail": { + "description": "Test case tracking" + }, + "braintrust": { + "description": "Logs & evaluations" + }, + "lumapps": { + "description": "Intranet pages & communities" + }, + "canvas": { + "description": "Courses, pages, & announcements" + }, + "craftFile": { + "description": "Files you uploaded" + }, + "federatedSlack": { + "description": "Search Slack at query time" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "Connector created successfully" }, "empty": { - "message": "It looks like you don't have any connectors setup yet. Visit the [Add Connector](/admin/add-connector) page to get started!" + "message": "It looks like you don't have any connectors setup yet. Visit the [Add Connector](/admin/connectors) page to get started!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "Add Connector" + "connectors": { + "label": "Connectors" }, "agents": { "label": "Agents" diff --git a/web/src/i18n/messages/es.json b/web/src/i18n/messages/es.json index a4b88b0c2c..f3a45391e6 100644 --- a/web/src/i18n/messages/es.json +++ b/web/src/i18n/messages/es.json @@ -779,41 +779,229 @@ "addConnector": { "categories": { "codeRepository": { - "label": "Repositorio de código" + "label": "Repositorios de código" }, "messaging": { "label": "Mensajería" }, - "other": { - "label": "Otros" - }, "sales": { - "label": "Ventas" + "label": "Ventas y GTM" }, "storage": { "label": "Almacenamiento en la nube" }, "ticketingAndTaskManagement": { - "label": "Tickets y gestión de tareas" + "label": "Tickets y tareas" }, "wiki": { "label": "Bases de conocimiento y wikis" + }, + "aiObservability": { + "label": "IA y observabilidad" + }, + "other": { + "label": "Otros" } }, "popular": { - "title": "Populares" + "title": "Añadir conector", + "description": "Conecta {appName} a tus fuentes de datos." }, "search": { - "placeholder": "Buscar conectores" - }, - "seeConnectorsButton": { - "label": "Ver los conectores" + "placeholder": "Buscar conectores..." }, "sourceTile": { "tooltip": { "federatedConfigured": "El conector federado ya está configurado. Haz clic para editar el conector existente.", "slackCredentialsFound": "Se encontraron credenciales de Slack existentes. Haz clic para gestionar tu conector de Slack." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "Conectar {source}" + } + }, + "sources": { + "web": { + "description": "Enlaza cualquier URL pública" + }, + "github": { + "description": "Código y pull requests" + }, + "gitlab": { + "description": "Código y CI/CD" + }, + "slack": { + "description": "Mensajería de equipo" + }, + "googleDrive": { + "description": "Archivos y carpetas compartidos" + }, + "gmail": { + "description": "Correo de Google" + }, + "bookstack": { + "description": "Wiki autoalojada" + }, + "outline": { + "description": "Wiki de equipo de código abierto" + }, + "confluence": { + "description": "Wiki de Atlassian" + }, + "jira": { + "description": "Gestor de issues de Atlassian" + }, + "productboard": { + "description": "Gestión de producto" + }, + "slab": { + "description": "Wiki de equipo" + }, + "coda": { + "description": "Documentos y bases de datos" + }, + "notion": { + "description": "Documentos y bases de datos" + }, + "guru": { + "description": "Base de conocimiento verificada" + }, + "gong": { + "description": "Inteligencia de llamadas de ventas" + }, + "zulip": { + "description": "Mensajería de código abierto" + }, + "linear": { + "description": "Gestor de issues de ingeniería" + }, + "hubspot": { + "description": "Marketing y CRM" + }, + "document360": { + "description": "Documentación de autoservicio" + }, + "file": { + "description": "Subir archivos locales" + }, + "userFile": { + "description": "Archivos subidos en el chat" + }, + "googleSites": { + "description": "Páginas alojadas en Google" + }, + "loopio": { + "description": "Respuestas a RFP" + }, + "box": { + "description": "Archivos, carpetas y notas" + }, + "dropbox": { + "description": "Archivos y carpetas compartidos" + }, + "discord": { + "description": "Mensajería de la comunidad" + }, + "salesforce": { + "description": "Ventas y CRM" + }, + "sharepoint": { + "description": "Intranet de Microsoft" + }, + "teams": { + "description": "Chats de equipo de Microsoft" + }, + "outlook": { + "description": "Correos y carpetas de correo" + }, + "zendesk": { + "description": "Tickets de soporte al cliente" + }, + "discourse": { + "description": "Foro de la comunidad" + }, + "axero": { + "description": "Intranet social" + }, + "clickup": { + "description": "Gestor de proyectos y tareas" + }, + "wikipedia": { + "description": "Base de conocimiento pública" + }, + "mediawiki": { + "description": "Wiki estilo Wikipedia" + }, + "asana": { + "description": "Gestión del trabajo" + }, + "s3": { + "description": "Buckets de almacenamiento de AWS" + }, + "r2": { + "description": "Buckets de almacenamiento en la nube" + }, + "googleCloudStorage": { + "description": "Buckets de Google Cloud" + }, + "xenforo": { + "description": "Foro de la comunidad" + }, + "ociStorage": { + "description": "Almacenamiento de objetos de OCI" + }, + "notApplicable": { + "description": "Sin fuente" + }, + "ingestionApi": { + "description": "Documentos enviados por la API" + }, + "freshdesk": { + "description": "Helpdesk de clientes" + }, + "fireflies": { + "description": "Notas de reuniones" + }, + "egnyte": { + "description": "Servicios de archivos gestionados" + }, + "airtable": { + "description": "Base de datos y tareas" + }, + "gitbook": { + "description": "Documentación para desarrolladores" + }, + "highspot": { + "description": "Habilitación de ventas" + }, + "drupalWiki": { + "description": "Wiki basada en CMS" + }, + "imap": { + "description": "Fuente de correo IMAP" + }, + "bitbucket": { + "description": "Control de código de Atlassian" + }, + "testrail": { + "description": "Seguimiento de casos de prueba" + }, + "braintrust": { + "description": "Registros y evaluaciones" + }, + "lumapps": { + "description": "Páginas y comunidades de la intranet" + }, + "canvas": { + "description": "Cursos, páginas y anuncios" + }, + "craftFile": { + "description": "Archivos que subiste" + }, + "federatedSlack": { + "description": "Buscar en Slack al consultar" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "El conector se creó correctamente" }, "empty": { - "message": "Parece que aún no tienes ningún conector configurado. ¡Ve a la página [Añadir conector](/admin/add-connector) para empezar!" + "message": "Parece que aún no tienes ningún conector configurado. ¡Ve a la página [Añadir conector](/admin/connectors) para empezar!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "Añadir conector" + "connectors": { + "label": "Conectores" }, "agents": { "label": "Agentes" diff --git a/web/src/i18n/messages/fr.json b/web/src/i18n/messages/fr.json index 39f00da3e6..87300154d4 100644 --- a/web/src/i18n/messages/fr.json +++ b/web/src/i18n/messages/fr.json @@ -779,41 +779,229 @@ "addConnector": { "categories": { "codeRepository": { - "label": "Dépôt de code" + "label": "Dépôts de code" }, "messaging": { "label": "Messagerie" }, - "other": { - "label": "Autres" - }, "sales": { - "label": "Ventes" + "label": "Ventes et GTM" }, "storage": { "label": "Stockage cloud" }, "ticketingAndTaskManagement": { - "label": "Tickets et gestion des tâches" + "label": "Tickets et tâches" }, "wiki": { "label": "Bases de connaissances et wikis" + }, + "aiObservability": { + "label": "IA et observabilité" + }, + "other": { + "label": "Autres" } }, "popular": { - "title": "Populaires" + "title": "Ajouter un connecteur", + "description": "Connectez {appName} à vos sources de données." }, "search": { - "placeholder": "Rechercher des connecteurs" - }, - "seeConnectorsButton": { - "label": "Voir les connecteurs" + "placeholder": "Rechercher des connecteurs..." }, "sourceTile": { "tooltip": { "federatedConfigured": "Connecteur fédéré déjà configuré. Cliquez pour modifier le connecteur existant.", "slackCredentialsFound": "Identifiants Slack existants trouvés. Cliquez pour gérer votre connecteur Slack." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "Connecter {source}" + } + }, + "sources": { + "web": { + "description": "Lier n'importe quelle URL publique" + }, + "github": { + "description": "Code et pull requests" + }, + "gitlab": { + "description": "Code et CI/CD" + }, + "slack": { + "description": "Messagerie d'équipe" + }, + "googleDrive": { + "description": "Fichiers et dossiers partagés" + }, + "gmail": { + "description": "Messagerie Google" + }, + "bookstack": { + "description": "Wiki auto-hébergé" + }, + "outline": { + "description": "Wiki d'équipe open source" + }, + "confluence": { + "description": "Wiki Atlassian" + }, + "jira": { + "description": "Suivi des tickets Atlassian" + }, + "productboard": { + "description": "Gestion de produit" + }, + "slab": { + "description": "Wiki d'équipe" + }, + "coda": { + "description": "Documents et bases de données" + }, + "notion": { + "description": "Documents et bases de données" + }, + "guru": { + "description": "Base de connaissances vérifiée" + }, + "gong": { + "description": "Analyse des appels commerciaux" + }, + "zulip": { + "description": "Messagerie open source" + }, + "linear": { + "description": "Suivi des tickets d'ingénierie" + }, + "hubspot": { + "description": "Marketing et CRM" + }, + "document360": { + "description": "Documentation en libre-service" + }, + "file": { + "description": "Importer des fichiers locaux" + }, + "userFile": { + "description": "Fichiers importés dans le chat" + }, + "googleSites": { + "description": "Pages hébergées par Google" + }, + "loopio": { + "description": "Réponses aux RFP" + }, + "box": { + "description": "Fichiers, dossiers et notes" + }, + "dropbox": { + "description": "Fichiers et dossiers partagés" + }, + "discord": { + "description": "Messagerie communautaire" + }, + "salesforce": { + "description": "Ventes et CRM" + }, + "sharepoint": { + "description": "Intranet Microsoft" + }, + "teams": { + "description": "Discussions d'équipe Microsoft" + }, + "outlook": { + "description": "E-mails et dossiers de messagerie" + }, + "zendesk": { + "description": "Tickets de support client" + }, + "discourse": { + "description": "Forum communautaire" + }, + "axero": { + "description": "Intranet social" + }, + "clickup": { + "description": "Suivi de projets et de tâches" + }, + "wikipedia": { + "description": "Base de connaissances publique" + }, + "mediawiki": { + "description": "Wiki de type Wikipédia" + }, + "asana": { + "description": "Gestion du travail" + }, + "s3": { + "description": "Buckets de stockage AWS" + }, + "r2": { + "description": "Buckets de stockage cloud" + }, + "googleCloudStorage": { + "description": "Buckets Google Cloud" + }, + "xenforo": { + "description": "Forum communautaire" + }, + "ociStorage": { + "description": "Stockage d'objets OCI" + }, + "notApplicable": { + "description": "Aucune source" + }, + "ingestionApi": { + "description": "Documents envoyés via l'API" + }, + "freshdesk": { + "description": "Helpdesk client" + }, + "fireflies": { + "description": "Notes de réunion" + }, + "egnyte": { + "description": "Services de fichiers gérés" + }, + "airtable": { + "description": "Base de données et tâches" + }, + "gitbook": { + "description": "Documentation développeur" + }, + "highspot": { + "description": "Sales enablement" + }, + "drupalWiki": { + "description": "Wiki basé sur un CMS" + }, + "imap": { + "description": "Source e-mail IMAP" + }, + "bitbucket": { + "description": "Gestion de code Atlassian" + }, + "testrail": { + "description": "Suivi des cas de test" + }, + "braintrust": { + "description": "Journaux et évaluations" + }, + "lumapps": { + "description": "Pages et communautés de l'intranet" + }, + "canvas": { + "description": "Cours, pages et annonces" + }, + "craftFile": { + "description": "Fichiers que vous avez importés" + }, + "federatedSlack": { + "description": "Rechercher dans Slack à la requête" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "Connecteur créé avec succès" }, "empty": { - "message": "Il semble que vous n'ayez pas encore configuré de connecteurs. Consultez la page [Ajouter un connecteur](/admin/add-connector) pour commencer !" + "message": "Il semble que vous n'ayez pas encore configuré de connecteurs. Consultez la page [Ajouter un connecteur](/admin/connectors) pour commencer !" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "Ajouter un connecteur" + "connectors": { + "label": "Connecteurs" }, "agents": { "label": "Agents" diff --git a/web/src/i18n/messages/ja.json b/web/src/i18n/messages/ja.json index 31d80e6675..2b03587d0b 100644 --- a/web/src/i18n/messages/ja.json +++ b/web/src/i18n/messages/ja.json @@ -784,36 +784,224 @@ "messaging": { "label": "メッセージング" }, - "other": { - "label": "その他" - }, "sales": { - "label": "営業" + "label": "営業・GTM" }, "storage": { "label": "クラウドストレージ" }, "ticketingAndTaskManagement": { - "label": "チケット管理・タスク管理" + "label": "チケット・タスク" }, "wiki": { "label": "ナレッジベース・Wiki" + }, + "aiObservability": { + "label": "AI・オブザーバビリティ" + }, + "other": { + "label": "その他" } }, "popular": { - "title": "人気" + "title": "コネクタを追加", + "description": "{appName} をデータソースに接続します。" }, "search": { - "placeholder": "コネクターを検索" - }, - "seeConnectorsButton": { - "label": "コネクターを表示" + "placeholder": "コネクターを検索..." }, "sourceTile": { "tooltip": { "federatedConfigured": "フェデレーテッドコネクターは設定済みです。 クリックすると、既存のコネクターを編集できます。", "slackCredentialsFound": "既存の Slack 資格情報が見つかりました。 クリックすると、Slack コネクターを管理できます。" } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "{source} を接続" + } + }, + "sources": { + "web": { + "description": "任意の公開 URL をリンク" + }, + "github": { + "description": "コードとプルリクエスト" + }, + "gitlab": { + "description": "コードと CI/CD" + }, + "slack": { + "description": "チームメッセージング" + }, + "googleDrive": { + "description": "共有ファイルとフォルダー" + }, + "gmail": { + "description": "Google のメール" + }, + "bookstack": { + "description": "セルフホスト型 Wiki" + }, + "outline": { + "description": "オープンソースのチーム Wiki" + }, + "confluence": { + "description": "Atlassian の Wiki" + }, + "jira": { + "description": "Atlassian の課題管理" + }, + "productboard": { + "description": "プロダクトマネジメント" + }, + "slab": { + "description": "チーム Wiki" + }, + "coda": { + "description": "ドキュメントとデータベース" + }, + "notion": { + "description": "ドキュメントとデータベース" + }, + "guru": { + "description": "検証済みナレッジベース" + }, + "gong": { + "description": "営業通話インテリジェンス" + }, + "zulip": { + "description": "オープンソースのメッセージング" + }, + "linear": { + "description": "エンジニアリング課題管理" + }, + "hubspot": { + "description": "マーケティングと CRM" + }, + "document360": { + "description": "セルフサービスドキュメント" + }, + "file": { + "description": "ローカルファイルからアップロード" + }, + "userFile": { + "description": "チャットでアップロードしたファイル" + }, + "googleSites": { + "description": "Google ホストのページ" + }, + "loopio": { + "description": "RFP 回答" + }, + "box": { + "description": "ファイル、フォルダー、ノート" + }, + "dropbox": { + "description": "共有ファイルとフォルダー" + }, + "discord": { + "description": "コミュニティメッセージング" + }, + "salesforce": { + "description": "営業と CRM" + }, + "sharepoint": { + "description": "Microsoft のイントラネット" + }, + "teams": { + "description": "Microsoft のチームチャット" + }, + "outlook": { + "description": "メールとメールフォルダー" + }, + "zendesk": { + "description": "カスタマーサポートのチケット" + }, + "discourse": { + "description": "コミュニティフォーラム" + }, + "axero": { + "description": "ソーシャルイントラネット" + }, + "clickup": { + "description": "プロジェクトとタスクの管理" + }, + "wikipedia": { + "description": "公開ナレッジベース" + }, + "mediawiki": { + "description": "Wikipedia 型の Wiki" + }, + "asana": { + "description": "ワークマネジメント" + }, + "s3": { + "description": "AWS ストレージバケット" + }, + "r2": { + "description": "クラウドストレージバケット" + }, + "googleCloudStorage": { + "description": "Google Cloud バケット" + }, + "xenforo": { + "description": "コミュニティフォーラム" + }, + "ociStorage": { + "description": "OCI オブジェクトストレージ" + }, + "notApplicable": { + "description": "ソースなし" + }, + "ingestionApi": { + "description": "API 経由で送信されたドキュメント" + }, + "freshdesk": { + "description": "カスタマーヘルプデスク" + }, + "fireflies": { + "description": "会議メモ" + }, + "egnyte": { + "description": "マネージドファイルサービス" + }, + "airtable": { + "description": "データベースとタスク" + }, + "gitbook": { + "description": "開発者向けドキュメント" + }, + "highspot": { + "description": "セールスイネーブルメント" + }, + "drupalWiki": { + "description": "CMS ベースの Wiki" + }, + "imap": { + "description": "IMAP メールソース" + }, + "bitbucket": { + "description": "Atlassian のソース管理" + }, + "testrail": { + "description": "テストケース管理" + }, + "braintrust": { + "description": "ログと評価" + }, + "lumapps": { + "description": "イントラネットのページとコミュニティ" + }, + "canvas": { + "description": "コース、ページ、お知らせ" + }, + "craftFile": { + "description": "アップロードしたファイル" + }, + "federatedSlack": { + "description": "クエリ時に Slack を検索" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "コネクターを作成しました" }, "empty": { - "message": "コネクターがまだ設定されていないようです。[コネクターを追加](/admin/add-connector) ページで開始してください。" + "message": "コネクターがまだ設定されていないようです。[コネクターを追加](/admin/connectors) ページで開始してください。" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "コネクターを追加" + "connectors": { + "label": "コネクター" }, "agents": { "label": "エージェント" diff --git a/web/src/i18n/messages/ko.json b/web/src/i18n/messages/ko.json index 55d00fc81b..e6f0e12ddb 100644 --- a/web/src/i18n/messages/ko.json +++ b/web/src/i18n/messages/ko.json @@ -784,36 +784,224 @@ "messaging": { "label": "메시징" }, - "other": { - "label": "기타" - }, "sales": { - "label": "영업" + "label": "영업 및 GTM" }, "storage": { "label": "클라우드 스토리지" }, "ticketingAndTaskManagement": { - "label": "티켓팅 및 작업 관리" + "label": "티켓 및 작업" }, "wiki": { "label": "지식 베이스 및 위키" + }, + "aiObservability": { + "label": "AI 및 관측 가능성" + }, + "other": { + "label": "기타" } }, "popular": { - "title": "인기" + "title": "커넥터 추가", + "description": "{appName}을(를) 데이터 소스에 연결하세요." }, "search": { - "placeholder": "커넥터 검색" - }, - "seeConnectorsButton": { - "label": "커넥터 보기" + "placeholder": "커넥터 검색..." }, "sourceTile": { "tooltip": { "federatedConfigured": "페더레이션 커넥터가 이미 구성되어 있습니다. 클릭하여 기존 커넥터를 편집하세요.", "slackCredentialsFound": "기존 Slack 자격 증명을 찾았습니다. 클릭하여 Slack 커넥터를 관리하세요." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "{source} 연결" + } + }, + "sources": { + "web": { + "description": "공개 URL 연결" + }, + "github": { + "description": "코드 및 풀 리퀘스트" + }, + "gitlab": { + "description": "코드 및 CI/CD" + }, + "slack": { + "description": "팀 메시징" + }, + "googleDrive": { + "description": "공유 파일과 폴더" + }, + "gmail": { + "description": "Google 이메일" + }, + "bookstack": { + "description": "자체 호스팅 위키" + }, + "outline": { + "description": "오픈소스 팀 위키" + }, + "confluence": { + "description": "Atlassian 위키" + }, + "jira": { + "description": "Atlassian 이슈 트래커" + }, + "productboard": { + "description": "제품 관리" + }, + "slab": { + "description": "팀 위키" + }, + "coda": { + "description": "문서 및 데이터베이스" + }, + "notion": { + "description": "문서 및 데이터베이스" + }, + "guru": { + "description": "검증된 지식 베이스" + }, + "gong": { + "description": "영업 통화 인텔리전스" + }, + "zulip": { + "description": "오픈소스 메시징" + }, + "linear": { + "description": "엔지니어링 이슈 트래커" + }, + "hubspot": { + "description": "마케팅 및 CRM" + }, + "document360": { + "description": "셀프서비스 문서" + }, + "file": { + "description": "로컬 파일 업로드" + }, + "userFile": { + "description": "채팅에서 업로드한 파일" + }, + "googleSites": { + "description": "Google 호스팅 페이지" + }, + "loopio": { + "description": "RFP 응답" + }, + "box": { + "description": "파일, 폴더, 노트" + }, + "dropbox": { + "description": "공유 파일과 폴더" + }, + "discord": { + "description": "커뮤니티 메시징" + }, + "salesforce": { + "description": "영업 및 CRM" + }, + "sharepoint": { + "description": "Microsoft 인트라넷" + }, + "teams": { + "description": "Microsoft 팀 채팅" + }, + "outlook": { + "description": "이메일과 메일 폴더" + }, + "zendesk": { + "description": "고객 지원 티켓" + }, + "discourse": { + "description": "커뮤니티 포럼" + }, + "axero": { + "description": "소셜 인트라넷" + }, + "clickup": { + "description": "프로젝트 및 작업 트래커" + }, + "wikipedia": { + "description": "공개 지식 베이스" + }, + "mediawiki": { + "description": "위키백과 스타일 위키" + }, + "asana": { + "description": "업무 관리" + }, + "s3": { + "description": "AWS 스토리지 버킷" + }, + "r2": { + "description": "클라우드 스토리지 버킷" + }, + "googleCloudStorage": { + "description": "Google Cloud 버킷" + }, + "xenforo": { + "description": "커뮤니티 포럼" + }, + "ociStorage": { + "description": "OCI 오브젝트 스토리지" + }, + "notApplicable": { + "description": "소스 없음" + }, + "ingestionApi": { + "description": "API로 전송된 문서" + }, + "freshdesk": { + "description": "고객 헬프데스크" + }, + "fireflies": { + "description": "회의 노트" + }, + "egnyte": { + "description": "관리형 파일 서비스" + }, + "airtable": { + "description": "데이터베이스 및 작업" + }, + "gitbook": { + "description": "개발자 문서" + }, + "highspot": { + "description": "세일즈 인에이블먼트" + }, + "drupalWiki": { + "description": "CMS 기반 위키" + }, + "imap": { + "description": "IMAP 이메일 소스" + }, + "bitbucket": { + "description": "Atlassian 소스 관리" + }, + "testrail": { + "description": "테스트 케이스 관리" + }, + "braintrust": { + "description": "로그와 평가" + }, + "lumapps": { + "description": "인트라넷 페이지와 커뮤니티" + }, + "canvas": { + "description": "강좌, 페이지, 공지" + }, + "craftFile": { + "description": "업로드한 파일" + }, + "federatedSlack": { + "description": "질의 시 Slack 검색" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "커넥터를 생성했습니다" }, "empty": { - "message": "아직 설정된 커넥터가 없는 것 같습니다. [커넥터 추가](/admin/add-connector) 페이지에서 시작하세요!" + "message": "아직 설정된 커넥터가 없는 것 같습니다. [커넥터 추가](/admin/connectors) 페이지에서 시작하세요!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "커넥터 추가" + "connectors": { + "label": "커넥터" }, "agents": { "label": "에이전트" diff --git a/web/src/i18n/messages/pt.json b/web/src/i18n/messages/pt.json index d2987ab21a..b4b5fedb05 100644 --- a/web/src/i18n/messages/pt.json +++ b/web/src/i18n/messages/pt.json @@ -779,41 +779,229 @@ "addConnector": { "categories": { "codeRepository": { - "label": "Repositório de código" + "label": "Repositórios de código" }, "messaging": { "label": "Mensagens" }, - "other": { - "label": "Outros" - }, "sales": { - "label": "Vendas" + "label": "Vendas e GTM" }, "storage": { "label": "Armazenamento em nuvem" }, "ticketingAndTaskManagement": { - "label": "Tíquetes e gestão de tarefas" + "label": "Tíquetes e tarefas" }, "wiki": { "label": "Base de conhecimento e wikis" + }, + "aiObservability": { + "label": "IA e observabilidade" + }, + "other": { + "label": "Outros" } }, "popular": { - "title": "Populares" + "title": "Adicionar conector", + "description": "Conecte o {appName} às suas fontes de dados." }, "search": { - "placeholder": "Pesquisar conectores" - }, - "seeConnectorsButton": { - "label": "Ver conectores" + "placeholder": "Pesquisar conectores..." }, "sourceTile": { "tooltip": { "federatedConfigured": "Conector federado já configurado. Clique para editar o conector existente.", "slackCredentialsFound": "Credenciais do Slack existentes encontradas. Clique para gerenciar seu conector do Slack." } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "Conectar {source}" + } + }, + "sources": { + "web": { + "description": "Vincule qualquer URL pública" + }, + "github": { + "description": "Código e pull requests" + }, + "gitlab": { + "description": "Código e CI/CD" + }, + "slack": { + "description": "Mensagens de equipe" + }, + "googleDrive": { + "description": "Arquivos e pastas compartilhados" + }, + "gmail": { + "description": "E-mail do Google" + }, + "bookstack": { + "description": "Wiki auto-hospedada" + }, + "outline": { + "description": "Wiki de equipe de código aberto" + }, + "confluence": { + "description": "Wiki da Atlassian" + }, + "jira": { + "description": "Rastreador de issues da Atlassian" + }, + "productboard": { + "description": "Gestão de produto" + }, + "slab": { + "description": "Wiki da equipe" + }, + "coda": { + "description": "Documentos e bancos de dados" + }, + "notion": { + "description": "Documentos e bancos de dados" + }, + "guru": { + "description": "Base de conhecimento verificada" + }, + "gong": { + "description": "Inteligência de chamadas de vendas" + }, + "zulip": { + "description": "Mensagens de código aberto" + }, + "linear": { + "description": "Rastreador de issues de engenharia" + }, + "hubspot": { + "description": "Marketing e CRM" + }, + "document360": { + "description": "Documentação de autoatendimento" + }, + "file": { + "description": "Enviar arquivos locais" + }, + "userFile": { + "description": "Arquivos enviados no chat" + }, + "googleSites": { + "description": "Páginas hospedadas pelo Google" + }, + "loopio": { + "description": "Respostas a RFP" + }, + "box": { + "description": "Arquivos, pastas e notas" + }, + "dropbox": { + "description": "Arquivos e pastas compartilhados" + }, + "discord": { + "description": "Mensagens da comunidade" + }, + "salesforce": { + "description": "Vendas e CRM" + }, + "sharepoint": { + "description": "Intranet da Microsoft" + }, + "teams": { + "description": "Chats de equipe da Microsoft" + }, + "outlook": { + "description": "E-mails e pastas de e-mail" + }, + "zendesk": { + "description": "Tickets de suporte ao cliente" + }, + "discourse": { + "description": "Fórum da comunidade" + }, + "axero": { + "description": "Intranet social" + }, + "clickup": { + "description": "Rastreador de projetos e tarefas" + }, + "wikipedia": { + "description": "Base de conhecimento pública" + }, + "mediawiki": { + "description": "Wiki no estilo Wikipédia" + }, + "asana": { + "description": "Gestão de trabalho" + }, + "s3": { + "description": "Buckets de armazenamento da AWS" + }, + "r2": { + "description": "Buckets de armazenamento em nuvem" + }, + "googleCloudStorage": { + "description": "Buckets do Google Cloud" + }, + "xenforo": { + "description": "Fórum da comunidade" + }, + "ociStorage": { + "description": "Armazenamento de objetos da OCI" + }, + "notApplicable": { + "description": "Sem fonte" + }, + "ingestionApi": { + "description": "Documentos enviados pela API" + }, + "freshdesk": { + "description": "Helpdesk de clientes" + }, + "fireflies": { + "description": "Notas de reunião" + }, + "egnyte": { + "description": "Serviços de arquivos gerenciados" + }, + "airtable": { + "description": "Banco de dados e tarefas" + }, + "gitbook": { + "description": "Documentação para desenvolvedores" + }, + "highspot": { + "description": "Capacitação de vendas" + }, + "drupalWiki": { + "description": "Wiki baseada em CMS" + }, + "imap": { + "description": "Fonte de e-mail IMAP" + }, + "bitbucket": { + "description": "Controle de código da Atlassian" + }, + "testrail": { + "description": "Acompanhamento de casos de teste" + }, + "braintrust": { + "description": "Logs e avaliações" + }, + "lumapps": { + "description": "Páginas e comunidades da intranet" + }, + "canvas": { + "description": "Cursos, páginas e avisos" + }, + "craftFile": { + "description": "Arquivos que você enviou" + }, + "federatedSlack": { + "description": "Pesquisar no Slack na consulta" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "Conector criado com sucesso" }, "empty": { - "message": "Parece que você ainda não configurou nenhum conector. Acesse a página [Adicionar conector](/admin/add-connector) para começar!" + "message": "Parece que você ainda não configurou nenhum conector. Acesse a página [Adicionar conector](/admin/connectors) para começar!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "Adicionar conector" + "connectors": { + "label": "Conectores" }, "agents": { "label": "Agentes" diff --git a/web/src/i18n/messages/zh.json b/web/src/i18n/messages/zh.json index a97ebdde9a..ea25b821df 100644 --- a/web/src/i18n/messages/zh.json +++ b/web/src/i18n/messages/zh.json @@ -784,36 +784,224 @@ "messaging": { "label": "即时通讯" }, - "other": { - "label": "其他" - }, "sales": { - "label": "销售" + "label": "销售与 GTM" }, "storage": { "label": "云存储" }, "ticketingAndTaskManagement": { - "label": "工单与任务管理" + "label": "工单与任务" }, "wiki": { "label": "知识库与 Wiki" + }, + "aiObservability": { + "label": "AI 与可观测性" + }, + "other": { + "label": "其他" } }, "popular": { - "title": "热门" + "title": "添加连接器", + "description": "将 {appName} 连接到您的数据源。" }, "search": { - "placeholder": "搜索连接器" - }, - "seeConnectorsButton": { - "label": "查看连接器" + "placeholder": "搜索连接器..." }, "sourceTile": { "tooltip": { "federatedConfigured": "联合连接器已配置。点击可编辑现有连接器。", "slackCredentialsFound": "已找到现有的 Slack 凭据。点击可管理您的 Slack 连接器。" } + }, + "sourceCard": { + "connectButton": { + "ariaLabel": "连接 {source}" + } + }, + "sources": { + "web": { + "description": "链接任意公开 URL" + }, + "github": { + "description": "代码与拉取请求" + }, + "gitlab": { + "description": "代码与 CI/CD" + }, + "slack": { + "description": "团队消息" + }, + "googleDrive": { + "description": "共享文件和文件夹" + }, + "gmail": { + "description": "Google 邮箱" + }, + "bookstack": { + "description": "自托管维基" + }, + "outline": { + "description": "开源团队维基" + }, + "confluence": { + "description": "Atlassian 维基" + }, + "jira": { + "description": "Atlassian 问题跟踪" + }, + "productboard": { + "description": "产品管理" + }, + "slab": { + "description": "团队维基" + }, + "coda": { + "description": "文档与数据库" + }, + "notion": { + "description": "文档与数据库" + }, + "guru": { + "description": "经验证的知识库" + }, + "gong": { + "description": "销售通话智能" + }, + "zulip": { + "description": "开源消息" + }, + "linear": { + "description": "工程问题跟踪" + }, + "hubspot": { + "description": "营销与 CRM" + }, + "document360": { + "description": "自助服务文档" + }, + "file": { + "description": "从本地文件上传" + }, + "userFile": { + "description": "聊天中上传的文件" + }, + "googleSites": { + "description": "Google 托管页面" + }, + "loopio": { + "description": "RFP 应答" + }, + "box": { + "description": "文件、文件夹和笔记" + }, + "dropbox": { + "description": "共享文件和文件夹" + }, + "discord": { + "description": "社区消息" + }, + "salesforce": { + "description": "销售与 CRM" + }, + "sharepoint": { + "description": "Microsoft 内网" + }, + "teams": { + "description": "Microsoft 团队聊天" + }, + "outlook": { + "description": "邮件和邮件文件夹" + }, + "zendesk": { + "description": "客户支持工单" + }, + "discourse": { + "description": "社区论坛" + }, + "axero": { + "description": "社交内网" + }, + "clickup": { + "description": "项目与任务跟踪" + }, + "wikipedia": { + "description": "公开知识库" + }, + "mediawiki": { + "description": "维基百科式维基" + }, + "asana": { + "description": "工作管理" + }, + "s3": { + "description": "AWS 存储桶" + }, + "r2": { + "description": "云存储桶" + }, + "googleCloudStorage": { + "description": "Google Cloud 存储桶" + }, + "xenforo": { + "description": "社区论坛" + }, + "ociStorage": { + "description": "OCI 对象存储" + }, + "notApplicable": { + "description": "无来源" + }, + "ingestionApi": { + "description": "通过 API 发送的文档" + }, + "freshdesk": { + "description": "客户服务台" + }, + "fireflies": { + "description": "会议记录" + }, + "egnyte": { + "description": "托管文件服务" + }, + "airtable": { + "description": "数据库与任务" + }, + "gitbook": { + "description": "开发者文档" + }, + "highspot": { + "description": "销售赋能" + }, + "drupalWiki": { + "description": "基于 CMS 的维基" + }, + "imap": { + "description": "IMAP 邮件来源" + }, + "bitbucket": { + "description": "Atlassian 源代码管理" + }, + "testrail": { + "description": "测试用例跟踪" + }, + "braintrust": { + "description": "日志和评估" + }, + "lumapps": { + "description": "内网页面和社区" + }, + "canvas": { + "description": "课程、页面和公告" + }, + "craftFile": { + "description": "你上传的文件" + }, + "federatedSlack": { + "description": "查询时搜索 Slack" + } } }, "agentStats": { @@ -5033,7 +5221,7 @@ "toast": "已成功创建连接器" }, "empty": { - "message": "您似乎还没有设置任何连接器。请访问[添加连接器](/admin/add-connector)页面开始使用!" + "message": "您似乎还没有设置任何连接器。请访问[添加连接器](/admin/connectors)页面开始使用!" }, "federated": { "access": { @@ -13374,8 +13562,8 @@ } }, "items": { - "addConnector": { - "label": "添加连接器" + "connectors": { + "label": "连接器" }, "agents": { "label": "智能体" diff --git a/web/src/lib/admin-routes.ts b/web/src/lib/admin-routes.ts index 7648a320ba..c9e3154fa8 100644 --- a/web/src/lib/admin-routes.ts +++ b/web/src/lib/admin-routes.ts @@ -19,6 +19,7 @@ import { SvgGlobe, SvgHistory, SvgImage, + SvgLinkedDots, SvgMcp, SvgOnyxOctagon, SvgPaintBrush, @@ -29,7 +30,6 @@ import { SvgSliders, SvgTerminal, SvgThumbsUp, - SvgUploadCloud, SvgUser, SvgUserCheck, SvgUserKey, @@ -231,21 +231,21 @@ export const ADMIN_ROUTES = { }, // ── Documents & Knowledge ───────────────────────────────────────── - INDEXING_STATUS: { - path: "/admin/indexing/status", - icon: SvgBookOpen, - title: "Existing Connectors", - sidebarLabel: "Existing Connectors", + CONNECTORS: { + path: "/admin/connectors", + icon: SvgLinkedDots, + title: "Connectors", + sidebarLabel: "Connectors", requiredPermission: Permission.MANAGE_CONNECTORS, section: "Documents & Knowledge", requiredTier: null, visibleWhen: (f: FeatureFlags) => f.vectorDbEnabled, }, - ADD_CONNECTOR: { - path: "/admin/add-connector", - icon: SvgUploadCloud, - title: "Add Connector", - sidebarLabel: "Add Connector", + INDEXING_STATUS: { + path: "/admin/indexing/status", + icon: SvgBookOpen, + title: "Existing Connectors", + sidebarLabel: "Existing Connectors", requiredPermission: Permission.MANAGE_CONNECTORS, section: "Documents & Knowledge", requiredTier: null, @@ -533,7 +533,7 @@ export function sidebarItem(route: AdminRouteEntry) { */ export const VECTOR_DB_REQUIRED_ROUTE_PREFIXES: readonly string[] = [ ADMIN_ROUTES.INDEXING_STATUS.path, - ADMIN_ROUTES.ADD_CONNECTOR.path, + ADMIN_ROUTES.CONNECTORS.path, // Covers /sets, /explorer, and /feedback — all require a vector DB. ADMIN_ROUTES.DOCUMENTS.path, ADMIN_ROUTES.INDEX_SETTINGS.path, diff --git a/web/src/lib/admin-sidebar-utils.ts b/web/src/lib/admin-sidebar-utils.ts index ad55c83edb..f57d0ee346 100644 --- a/web/src/lib/admin-sidebar-utils.ts +++ b/web/src/lib/admin-sidebar-utils.ts @@ -31,7 +31,7 @@ export type AdminNavItemId = | "mcpActions" | "openapiActions" | "existingConnectors" - | "addConnector" + | "connectors" | "documentSets" | "indexSettings" | "serviceAccounts" @@ -87,7 +87,7 @@ export const NAV_ITEM_IDS: Record< MCP_ACTIONS: "mcpActions", OPENAPI_ACTIONS: "openapiActions", INDEXING_STATUS: "existingConnectors", - ADD_CONNECTOR: "addConnector", + CONNECTORS: "connectors", DOCUMENT_SETS: "documentSets", DOCUMENT_EXPLORER: null, DOCUMENT_FEEDBACK: null, diff --git a/web/src/lib/adminNavLabels.tsx b/web/src/lib/adminNavLabels.tsx index f900edf3b1..b08220af4b 100644 --- a/web/src/lib/adminNavLabels.tsx +++ b/web/src/lib/adminNavLabels.tsx @@ -29,7 +29,7 @@ export function useAdminNavLabels(): Record { mcpActions: t("adminNav.items.mcpActions.label"), openapiActions: t("adminNav.items.openapiActions.label"), existingConnectors: t("adminNav.items.existingConnectors.label"), - addConnector: t("adminNav.items.addConnector.label"), + connectors: t("adminNav.items.connectors.label"), documentSets: t("adminNav.items.documentSets.label"), indexSettings: t("adminNav.items.indexSettings.label"), serviceAccounts: t("adminNav.items.serviceAccounts.label"), diff --git a/web/src/lib/connectors/components.tsx b/web/src/lib/connectors/components.tsx new file mode 100644 index 0000000000..e60695d69d --- /dev/null +++ b/web/src/lib/connectors/components.tsx @@ -0,0 +1,72 @@ +"use client"; + +import type { Route } from "next"; +import { useRouter } from "next/navigation"; +import { useTranslations } from "next-intl"; +import { Button, SelectCard } from "@opal/components"; +import { ContentAction } from "@opal/layouts"; +import { SvgPlusCircle } from "@opal/icons"; +import type { SourceMetadata } from "@/lib/search/types"; + +export interface ConnectorSourceCardProps { + sourceMetadata: SourceMetadata; + /** Translated one-line summary of what the source indexes, shown under its name. */ + description: string; + /** Where the card and its add button lead: the setup wizard, or an + * existing federated connector's edit page. */ + navigationUrl: Route; +} + +/** + * One source in the connector catalog: the card counterpart to the + * "Add Provider" cards on the Language Models page. The whole card is the + * target; the add button repeats it for discoverability. + */ +export function ConnectorSourceCard({ + sourceMetadata, + description, + navigationUrl, +}: ConnectorSourceCardProps) { + const t = useTranslations("admin.addConnector"); + const router = useRouter(); + const navigate = () => router.push(navigationUrl); + + return ( + ", so an exact + // match on the bare name reaches the card alone. + aria-label={sourceMetadata.displayName} + onClick={navigate} + > + { + e.stopPropagation(); + navigate(); + }} + /> + } + /> + + ); +} diff --git a/web/src/lib/connectors/constants.ts b/web/src/lib/connectors/constants.ts new file mode 100644 index 0000000000..13d6b9962a --- /dev/null +++ b/web/src/lib/connectors/constants.ts @@ -0,0 +1,90 @@ +import { SourceCategory } from "@/lib/search/types"; +import { ValidSources } from "@/lib/types"; + +/** + * Message key, inside the `admin.addConnector` namespace, for each category + * heading in the connector catalog. The enum values are identifiers shared + * across the app, so the labels live in the catalog rather than the enum. + */ +export const SOURCE_CATEGORY_LABEL_KEYS = { + [SourceCategory.Wiki]: "categories.wiki.label", + [SourceCategory.Storage]: "categories.storage.label", + [SourceCategory.TicketingAndTaskManagement]: + "categories.ticketingAndTaskManagement.label", + [SourceCategory.Messaging]: "categories.messaging.label", + [SourceCategory.Sales]: "categories.sales.label", + [SourceCategory.CodeRepository]: "categories.codeRepository.label", + [SourceCategory.AiObservability]: "categories.aiObservability.label", + [SourceCategory.Other]: "categories.other.label", +} as const satisfies Record; + +/** The catalog sections, in display order. */ +export const CATALOG_CATEGORIES = Object.values(SourceCategory); + +/** + * Message key, inside the `admin.addConnector` namespace, for the one-line + * summary shown under each source in the connector catalog. Keyed by every + * `ValidSources` member so a new source cannot ship without a summary. + */ +export const SOURCE_DESCRIPTION_KEYS = { + [ValidSources.Web]: "sources.web.description", + [ValidSources.GitHub]: "sources.github.description", + [ValidSources.GitLab]: "sources.gitlab.description", + [ValidSources.Slack]: "sources.slack.description", + [ValidSources.GoogleDrive]: "sources.googleDrive.description", + [ValidSources.Gmail]: "sources.gmail.description", + [ValidSources.Bookstack]: "sources.bookstack.description", + [ValidSources.Outline]: "sources.outline.description", + [ValidSources.Confluence]: "sources.confluence.description", + [ValidSources.Jira]: "sources.jira.description", + [ValidSources.Productboard]: "sources.productboard.description", + [ValidSources.Slab]: "sources.slab.description", + [ValidSources.Coda]: "sources.coda.description", + [ValidSources.Notion]: "sources.notion.description", + [ValidSources.Guru]: "sources.guru.description", + [ValidSources.Gong]: "sources.gong.description", + [ValidSources.Zulip]: "sources.zulip.description", + [ValidSources.Linear]: "sources.linear.description", + [ValidSources.Hubspot]: "sources.hubspot.description", + [ValidSources.Document360]: "sources.document360.description", + [ValidSources.File]: "sources.file.description", + [ValidSources.UserFile]: "sources.userFile.description", + [ValidSources.GoogleSites]: "sources.googleSites.description", + [ValidSources.Loopio]: "sources.loopio.description", + [ValidSources.Box]: "sources.box.description", + [ValidSources.Dropbox]: "sources.dropbox.description", + [ValidSources.Discord]: "sources.discord.description", + [ValidSources.Salesforce]: "sources.salesforce.description", + [ValidSources.Sharepoint]: "sources.sharepoint.description", + [ValidSources.Teams]: "sources.teams.description", + [ValidSources.Outlook]: "sources.outlook.description", + [ValidSources.Zendesk]: "sources.zendesk.description", + [ValidSources.Discourse]: "sources.discourse.description", + [ValidSources.Axero]: "sources.axero.description", + [ValidSources.Clickup]: "sources.clickup.description", + [ValidSources.Wikipedia]: "sources.wikipedia.description", + [ValidSources.Mediawiki]: "sources.mediawiki.description", + [ValidSources.Asana]: "sources.asana.description", + [ValidSources.S3]: "sources.s3.description", + [ValidSources.R2]: "sources.r2.description", + [ValidSources.GoogleCloudStorage]: "sources.googleCloudStorage.description", + [ValidSources.Xenforo]: "sources.xenforo.description", + [ValidSources.OciStorage]: "sources.ociStorage.description", + [ValidSources.NotApplicable]: "sources.notApplicable.description", + [ValidSources.IngestionApi]: "sources.ingestionApi.description", + [ValidSources.Freshdesk]: "sources.freshdesk.description", + [ValidSources.Fireflies]: "sources.fireflies.description", + [ValidSources.Egnyte]: "sources.egnyte.description", + [ValidSources.Airtable]: "sources.airtable.description", + [ValidSources.Gitbook]: "sources.gitbook.description", + [ValidSources.Highspot]: "sources.highspot.description", + [ValidSources.DrupalWiki]: "sources.drupalWiki.description", + [ValidSources.Imap]: "sources.imap.description", + [ValidSources.Bitbucket]: "sources.bitbucket.description", + [ValidSources.TestRail]: "sources.testrail.description", + [ValidSources.Braintrust]: "sources.braintrust.description", + [ValidSources.Lumapps]: "sources.lumapps.description", + [ValidSources.Canvas]: "sources.canvas.description", + [ValidSources.CraftFile]: "sources.craftFile.description", + [ValidSources.FederatedSlack]: "sources.federatedSlack.description", +} as const satisfies Record; diff --git a/web/src/lib/search/types.ts b/web/src/lib/search/types.ts index f6ba6f462d..a65458b3e2 100644 --- a/web/src/lib/search/types.ts +++ b/web/src/lib/search/types.ts @@ -125,7 +125,8 @@ export enum SourceCategory { Messaging = "Messaging", Sales = "Sales", CodeRepository = "Code Repository", - Other = "Others", + AiObservability = "AI & Observability", + Other = "Other", } export interface SourceMetadata { diff --git a/web/src/lib/sources.ts b/web/src/lib/sources.ts index 9e9f7017b6..086459ff7e 100644 --- a/web/src/lib/sources.ts +++ b/web/src/lib/sources.ts @@ -445,7 +445,7 @@ export const SOURCE_METADATA_MAP: SourceMap = { braintrust: { icon: BraintrustIcon, displayName: "Braintrust", - category: SourceCategory.Other, + category: SourceCategory.AiObservability, }, // Other diff --git a/web/src/lib/tools/components/ToolLineItem.tsx b/web/src/lib/tools/components/ToolLineItem.tsx index a5e06a4f3d..c163c0dffd 100644 --- a/web/src/lib/tools/components/ToolLineItem.tsx +++ b/web/src/lib/tools/components/ToolLineItem.tsx @@ -1,6 +1,7 @@ "use client"; import { Fragment, useMemo } from "react"; +import { ADMIN_ROUTES } from "@/lib/admin-routes"; import { useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import type { Route } from "next"; @@ -265,7 +266,7 @@ export default function ToolLineItem({ tool }: ToolLineItemProps) { aria-label={connectorsLabel} tooltip={connectorsLabel} onClick={() => { - if (needsConnectors) router.push("/admin/add-connector"); + if (needsConnectors) router.push(ADMIN_ROUTES.CONNECTORS.path); else openSources(); }} /> diff --git a/web/src/sections/sidebar/CreateConnectorSidebar.tsx b/web/src/sections/sidebar/CreateConnectorSidebar.tsx index aded9b80ba..ba1ea84316 100644 --- a/web/src/sections/sidebar/CreateConnectorSidebar.tsx +++ b/web/src/sections/sidebar/CreateConnectorSidebar.tsx @@ -1,6 +1,7 @@ "use client"; import { Fragment, ReactNode } from "react"; +import { ADMIN_ROUTES } from "@/lib/admin-routes"; import { useTranslations } from "next-intl"; import { useFormContext } from "@/components/context/FormContext"; import { credentialTemplates } from "@/lib/connectors/credentials"; @@ -72,7 +73,7 @@ export function CreateConnectorSidebarShell({ {!folded && } diff --git a/web/src/app/admin/add-connector/page.tsx b/web/src/views/admin/ConnectorsPage.tsx similarity index 54% rename from web/src/app/admin/add-connector/page.tsx rename to web/src/views/admin/ConnectorsPage.tsx index 19e8e0a2de..03e43b61b8 100644 --- a/web/src/app/admin/add-connector/page.tsx +++ b/web/src/views/admin/ConnectorsPage.tsx @@ -1,10 +1,12 @@ "use client"; + +import type { Route } from "next"; import { useAdminRouteTitle } from "@/lib/adminNavLabels"; import { useTranslations } from "next-intl"; -import { SettingsLayouts } from "@opal/layouts"; +import { Content, SettingsLayouts } from "@opal/layouts"; +import * as GeneralLayouts from "@/layouts/general-layouts"; import { SourceCategory, SourceMetadata } from "@/lib/search/types"; import { listSourceMetadata } from "@/lib/sources"; -import { Button } from "@opal/components"; import { useCallback, useDeferredValue, @@ -13,7 +15,8 @@ import { useRef, useState, } from "react"; -import { Tooltip } from "@opal/components"; +import { Tooltip, InputTypeIn, Text } from "@opal/components"; +import { richNodes } from "@opal/utils"; import { useFederatedConnectors } from "@/lib/hooks"; import { FederatedConnectorDetail, @@ -25,39 +28,32 @@ import { errorHandlingFetcher } from "@/lib/fetcher"; import { buildSimilarCredentialInfoURL } from "@/app/admin/connector/[ccPairId]/lib"; import { Credential } from "@/lib/connectors/credentials"; import { useSettings } from "@/lib/settings/hooks"; -import SourceTile from "@/components/SourceTile"; -import { InputTypeIn } from "@opal/components"; -import Text from "@/refresh-components/texts/Text"; +import { ConnectorSourceCard } from "@/lib/connectors/components"; import { ADMIN_ROUTES } from "@/lib/admin-routes"; +import { + CATALOG_CATEGORIES, + SOURCE_CATEGORY_LABEL_KEYS, + SOURCE_DESCRIPTION_KEYS, +} from "@/lib/connectors/constants"; -const route = ADMIN_ROUTES.ADD_CONNECTOR; +const route = ADMIN_ROUTES.CONNECTORS; -// The category headings come from the `SourceCategory` enum, whose values are -// identifiers shared across the app. Map each one to a message key (inside the -// `admin.addConnector` namespace) so the component can resolve it with `t`. -const CATEGORY_LABEL_KEYS = { - [SourceCategory.Wiki]: "categories.wiki.label", - [SourceCategory.Storage]: "categories.storage.label", - [SourceCategory.TicketingAndTaskManagement]: - "categories.ticketingAndTaskManagement.label", - [SourceCategory.Messaging]: "categories.messaging.label", - [SourceCategory.Sales]: "categories.sales.label", - [SourceCategory.CodeRepository]: "categories.codeRepository.label", - [SourceCategory.Other]: "categories.other.label", -} as const satisfies Record; +// Four columns at the full settings width, three and then two as the +// `sourcecards` container narrows. +const SOURCE_CARD_GRID = + "grid grid-cols-2 @xl/sourcecards:grid-cols-3 @3xl/sourcecards:grid-cols-4 gap-2"; function SourceTileTooltipWrapper({ sourceMetadata, - preSelect, federatedConnectors, slackCredentials, }: { sourceMetadata: SourceMetadata; - preSelect?: boolean; federatedConnectors?: FederatedConnectorDetail[]; slackCredentials?: Credential[]; }) { const t = useTranslations("admin.addConnector"); + const description = t(SOURCE_DESCRIPTION_KEYS[sourceMetadata.internalName]); // Check if there's already a federated connector for this source const existingFederatedConnector = useMemo(() => { @@ -82,11 +78,11 @@ function SourceTileTooltipWrapper({ const navigationUrl = useMemo(() => { // If there's an existing federated connector, route to edit it if (existingFederatedConnector) { - return `/admin/federated/${existingFederatedConnector.id}`; + return `/admin/federated/${existingFederatedConnector.id}` as Route; } // For all other sources (including Slack), use the regular admin URL - return sourceMetadata.adminUrl; + return sourceMetadata.adminUrl as Route; }, [existingFederatedConnector, sourceMetadata]); // Compute whether to hide the tooltip @@ -98,11 +94,10 @@ function SourceTileTooltipWrapper({ // If tooltip should be hidden, just render the tile as a component if (shouldHideTooltip) { return ( - ); } @@ -112,33 +107,34 @@ function SourceTileTooltipWrapper({ side="top" tooltip={ existingFederatedConnector ? ( - - {t.rich("sourceTile.tooltip.federatedConfigured", { - strong: (chunks) => {chunks}, - })} + + {richNodes( + t.rich("sourceTile.tooltip.federatedConfigured", { + strong: (chunks) => {chunks}, + }) + )} ) : hasExistingSlackCredentials ? ( - - {t.rich("sourceTile.tooltip.slackCredentialsFound", { - strong: (chunks) => {chunks}, - })} + + {richNodes( + t.rich("sourceTile.tooltip.slackCredentialsFound", { + strong: (chunks) => {chunks}, + }) + )} ) : undefined } > -
- -
+ ); } -export default function Page() { +export default function ConnectorsPage() { const t = useTranslations("admin.addConnector"); const adminRouteTitle = useAdminRouteTitle(); const sources = useMemo(() => listSourceMetadata(), []); @@ -148,6 +144,7 @@ export default function Page() { const { data: federatedConnectors } = useFederatedConnectors(); const settings = useSettings(); + const { appName } = settings; // Fetch Slack credentials to determine navigation behavior const { data: slackCredentials } = useSWR[]>( @@ -188,7 +185,7 @@ export default function Page() { const categorizedSources = useMemo(() => { const filtered = filterSources(sources); - const categories = Object.values(SourceCategory).reduce( + const categories = CATALOG_CATEGORIES.reduce( (acc, category) => { acc[category] = sources.filter( (source) => @@ -200,10 +197,10 @@ export default function Page() { }, {} as Record ); - // Filter out the "Other" category if show_extra_connectors is false + // The extra-connectors setting hides the AI & Observability section. if (settings?.show_extra_connectors === false) { const filteredCategories = Object.entries(categories).filter( - ([category]) => category !== SourceCategory.Other + ([category]) => category !== SourceCategory.AiObservability ); return Object.fromEntries(filteredCategories) as Record< SourceCategory, @@ -228,102 +225,104 @@ export default function Page() { return popularSources.filter((s) => !resultIds.has(s.internalName)); }, [popularSources, resultIds, searchTerm]); - const handleKeyPress = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { - const filteredCategories = Object.entries(categorizedSources).filter( - ([_, sources]) => sources.length > 0 - ); - if ( - filteredCategories.length > 0 && - filteredCategories[0] !== undefined && - filteredCategories[0][1].length > 0 - ) { - const firstSource = filteredCategories[0][1][0]; - if (firstSource) { - // Check if this source has an existing federated connector - const existingFederatedConnector = - firstSource.federated && federatedConnectors - ? federatedConnectors.find( - (connector) => - connector.source === `federated_${firstSource.internalName}` - ) - : null; - - const url = existingFederatedConnector - ? `/admin/federated/${existingFederatedConnector.id}` - : firstSource.adminUrl; - - window.open(url, "_self"); - } - } - } + // Enter or ArrowDown in the search field moves focus to the first card; + // a focused card opens on Enter. + const catalogRef = useRef(null); + const handleSearchKeyDown = (e: React.KeyboardEvent) => { + if (e.key !== "Enter" && e.key !== "ArrowDown") return; + const card = + catalogRef.current?.querySelector("[data-source-card]"); + if (!card) return; + e.preventDefault(); + card.focus(); }; return ( - - - {t("seeConnectorsButton.label")} - - } - divider - /> - + + setSearchTerm(event.target.value)} - onKeyDown={handleKeyPress} + onKeyDown={handleSearchKeyDown} /> + + +
+ + + + {dedupedPopular.length > 0 && ( + +
+ {dedupedPopular.map((source) => ( + + ))} +
+
+ )} - {dedupedPopular.length > 0 && ( -
- - {t("popular.title")} - -
- {dedupedPopular.map((source) => ( - - ))} -
-
- )} - - {Object.entries(categorizedSources) - .filter(([_, sources]) => sources.length > 0) - .map(([category, sources], categoryInd) => ( -
- - {t(CATEGORY_LABEL_KEYS[category as SourceCategory])} - -
- {sources.map((source, sourceInd) => ( - 0 && - categoryInd == 0 && - sourceInd == 0 - } - key={source.internalName} - sourceMetadata={source} - federatedConnectors={federatedConnectors} - slackCredentials={slackCredentials} - /> + {Object.entries(categorizedSources) + .filter(([_, sources]) => sources.length > 0) + .map(([category, sources]) => ( + + + {t( + SOURCE_CATEGORY_LABEL_KEYS[category as SourceCategory] + )} + +
+ {sources.map((source) => ( + + ))} +
+
))} -
-
- ))} +
+
+
); diff --git a/web/tests/e2e/admin/connector/ConnectorCatalogPage.ts b/web/tests/e2e/admin/connector/ConnectorCatalogPage.ts new file mode 100644 index 0000000000..b68df1ebac --- /dev/null +++ b/web/tests/e2e/admin/connector/ConnectorCatalogPage.ts @@ -0,0 +1,37 @@ +/** + * Page Object Model for the connector catalog (`/admin/connectors`). + * + * Every source renders as a card whose add button is labelled + * "Connect ". Popular sources appear twice (in the popular grid and in + * their category), so actions target the first match. + */ + +import { expect, type Locator, type Page } from "@playwright/test"; + +export class ConnectorCatalogPage { + readonly page: Page; + readonly pageTitle: Locator; + + constructor(page: Page) { + this.page = page; + this.pageTitle = page.locator('[aria-label="admin-page-title"]'); + } + + async goto() { + await this.page.goto("/admin/connectors"); + await expect(this.pageTitle).toBeVisible({ timeout: 10_000 }); + } + + /** The add button on a source's card, by the source's display name. */ + connectButton(displayName: string): Locator { + return this.page + .getByRole("button", { name: `Connect ${displayName}` }) + .first(); + } + + /** Open a source's setup flow from its card. */ + async openSource(displayName: string) { + await this.connectButton(displayName).click(); + await this.page.waitForLoadState("networkidle"); + } +} diff --git a/web/tests/e2e/admin/connector/ConnectorSetupPage.ts b/web/tests/e2e/admin/connector/ConnectorSetupPage.ts index 429dd054ca..156ec76c5c 100644 --- a/web/tests/e2e/admin/connector/ConnectorSetupPage.ts +++ b/web/tests/e2e/admin/connector/ConnectorSetupPage.ts @@ -1,5 +1,5 @@ /** - * Page Object Model for the add-connector wizard + * Page Object Model for the connector setup wizard * (`/admin/connectors/?step=1`). * * The wizard renders every connector's configuration form through the shared diff --git a/web/tests/e2e/admin/group-manager/page-access.spec.ts b/web/tests/e2e/admin/group-manager/page-access.spec.ts index 4c71f683aa..efa666aac9 100644 --- a/web/tests/e2e/admin/group-manager/page-access.spec.ts +++ b/web/tests/e2e/admin/group-manager/page-access.spec.ts @@ -20,7 +20,7 @@ const PAGE_HEADINGS: Record = { [ADMIN_ROUTES.MCP_ACTIONS.path]: "MCP Actions", [ADMIN_ROUTES.OPENAPI_ACTIONS.path]: "OpenAPI Actions", [ADMIN_ROUTES.INDEXING_STATUS.path]: "Existing Connectors", - [ADMIN_ROUTES.ADD_CONNECTOR.path]: "Add Connector", + [ADMIN_ROUTES.CONNECTORS.path]: "Connectors", [ADMIN_ROUTES.DOCUMENT_SETS.path]: "Document Sets", }; @@ -33,7 +33,7 @@ const ALWAYS_PAGES = [ /** Also require `vectorDbEnabled`. */ const VECTOR_DB_PAGES = [ - ADMIN_ROUTES.ADD_CONNECTOR.path, + ADMIN_ROUTES.CONNECTORS.path, ADMIN_ROUTES.DOCUMENT_SETS.path, ADMIN_ROUTES.INDEXING_STATUS.path, ]; diff --git a/web/tests/e2e/admin/permissions/permission_gating.spec.ts b/web/tests/e2e/admin/permissions/permission_gating.spec.ts index c654277b02..404d84d615 100644 --- a/web/tests/e2e/admin/permissions/permission_gating.spec.ts +++ b/web/tests/e2e/admin/permissions/permission_gating.spec.ts @@ -273,8 +273,8 @@ test.describe("Permission gating — MANAGE_CONNECTORS", () => { await page.waitForLoadState("networkidle"); expect(page.url()).toContain("/app"); - // Also verify /admin/add-connector redirects - await page.goto(ADMIN_ROUTES.ADD_CONNECTOR.path); + // Also verify /admin/connectors redirects + await page.goto(ADMIN_ROUTES.CONNECTORS.path); await page.waitForLoadState("networkidle"); expect(page.url()).toContain("/app"); @@ -296,16 +296,16 @@ test.describe("Permission gating — MANAGE_CONNECTORS", () => { ).toBeVisible({ timeout: 10000 }); await expect(page.getByRole("table")).toBeVisible(); - // Also verify /admin/add-connector is accessible - await page.goto(ADMIN_ROUTES.ADD_CONNECTOR.path); + // Also verify /admin/connectors is accessible + await page.goto(ADMIN_ROUTES.CONNECTORS.path); await page.waitForLoadState("networkidle"); - expect(page.url()).toContain(ADMIN_ROUTES.ADD_CONNECTOR.path); + expect(page.url()).toContain(ADMIN_ROUTES.CONNECTORS.path); await expect( - page.getByLabel("admin-page-title").getByText("Add Connector") + page.getByLabel("admin-page-title").getByText("Connectors") ).toBeVisible({ timeout: 10000 }); // Access type and groups live on the wizard's second step, so reaching - // /admin/add-connector says nothing about them. `web` has no credential + // /admin/connectors says nothing about them. `web` has no credential // template, so the wizard skips straight there. await page.goto("/admin/connectors/web"); await page.waitForLoadState("networkidle"); diff --git a/web/tests/e2e/connectors/federated_slack.spec.ts b/web/tests/e2e/connectors/federated_slack.spec.ts index f0765c6b9d..2b44cc45a8 100644 --- a/web/tests/e2e/connectors/federated_slack.spec.ts +++ b/web/tests/e2e/connectors/federated_slack.spec.ts @@ -1,6 +1,7 @@ import { test, expect } from "@playwright/test"; import type { Page } from "@playwright/test"; import { loginAs, loginAsRandomUser } from "@tests/e2e/utils/auth"; +import { ConnectorCatalogPage } from "@tests/e2e/admin/connector/ConnectorCatalogPage"; test.use({ storageState: "admin_auth.json" }); @@ -8,13 +9,9 @@ const SLACK_CLIENT_ID = process.env.SLACK_CLIENT_ID; const SLACK_CLIENT_SECRET = process.env.SLACK_CLIENT_SECRET; async function createFederatedSlackConnector(page: Page) { - // Navigate to add connector page - await page.goto("/admin/add-connector"); - await page.waitForLoadState("networkidle"); - - // Click on Slack connector tile (specifically the one with "Logo Slack" text, not "Slack Bots") - await page.getByRole("link", { name: "Logo Slack" }).first().click(); - await page.waitForLoadState("networkidle"); + const catalog = new ConnectorCatalogPage(page); + await catalog.goto(); + await catalog.openSource("Slack"); if (!SLACK_CLIENT_ID || !SLACK_CLIENT_SECRET) { throw new Error("SLACK_CLIENT_ID and SLACK_CLIENT_SECRET must be set");