(fix:locales) sync static text

This commit is contained in:
ManishMadan2882 committed 2025-01-16 18:24:27 +05:30
1 parent cbcb717aee
commit cc78ea7222
14 files changed
+383 -163

No files matched your search

+10 -6
View File
@@ -1,4 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import SingleArrowLeft from '../assets/single-left-arrow.svg'; import SingleArrowLeft from '../assets/single-left-arrow.svg';
import SingleArrowRight from '../assets/single-right-arrow.svg'; import SingleArrowRight from '../assets/single-right-arrow.svg';
import DoubleArrowLeft from '../assets/double-arrow-left.svg'; import DoubleArrowLeft from '../assets/double-arrow-left.svg';
@@ -19,6 +20,7 @@ const Pagination: React.FC<PaginationProps> = ({
onPageChange, onPageChange,
onRowsPerPageChange, onRowsPerPageChange,
}) => { }) => {
const { t } = useTranslation();
const [isDropdownOpen, setIsDropdownOpen] = useState(false); const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const rowsPerPageOptions = [5, 10, 20, 50]; const rowsPerPageOptions = [5, 10, 20, 50];
@@ -53,7 +55,9 @@ const Pagination: React.FC<PaginationProps> = ({
<div className="flex items-center text-xs justify-end gap-4 mt-2 p-2 border-gray-200"> <div className="flex items-center text-xs justify-end gap-4 mt-2 p-2 border-gray-200">
{/* Rows per page dropdown */} {/* Rows per page dropdown */}
<div className="flex items-center gap-2 relative"> <div className="flex items-center gap-2 relative">
<span className="text-gray-900 dark:text-gray-50">Rows per page:</span> <span className="text-gray-900 dark:text-gray-50">
{t('pagination.rowsPerPage')}:
</span>
<div className="relative"> <div className="relative">
<button <button
onClick={toggleDropdown} onClick={toggleDropdown}
@@ -87,7 +91,7 @@ const Pagination: React.FC<PaginationProps> = ({
{/* Pagination controls */} {/* Pagination controls */}
<div className="text-gray-900 dark:text-gray-50"> <div className="text-gray-900 dark:text-gray-50">
Page {currentPage} of {totalPages} {t('pagination.pageOf', { currentPage, totalPages })}
</div> </div>
<div className="flex items-center gap-2 text-gray-900 dark:text-gray-50"> <div className="flex items-center gap-2 text-gray-900 dark:text-gray-50">
<button <button
@@ -97,7 +101,7 @@ const Pagination: React.FC<PaginationProps> = ({
> >
<img <img
src={DoubleArrowLeft} src={DoubleArrowLeft}
alt="First page" alt={t('pagination.firstPage')}
className="dark:invert dark:sepia dark:brightness-200" className="dark:invert dark:sepia dark:brightness-200"
/> />
</button> </button>
@@ -108,7 +112,7 @@ const Pagination: React.FC<PaginationProps> = ({
> >
<img <img
src={SingleArrowLeft} src={SingleArrowLeft}
alt="Previous page" alt={t('pagination.previousPage')}
className="dark:invert dark:sepia dark:brightness-200" className="dark:invert dark:sepia dark:brightness-200"
/> />
</button> </button>
@@ -119,7 +123,7 @@ const Pagination: React.FC<PaginationProps> = ({
> >
<img <img
src={SingleArrowRight} src={SingleArrowRight}
alt="Next page" alt={t('pagination.nextPage')}
className="dark:invert dark:sepia dark:brightness-200" className="dark:invert dark:sepia dark:brightness-200"
/> />
</button> </button>
@@ -130,7 +134,7 @@ const Pagination: React.FC<PaginationProps> = ({
> >
<img <img
src={DoubleArrowRight} src={DoubleArrowRight}
alt="Last page" alt={t('pagination.lastPage')}
className="dark:invert dark:sepia dark:brightness-200" className="dark:invert dark:sepia dark:brightness-200"
/> />
</button> </button>
+35 -2
View File
@@ -83,7 +83,9 @@
"tokenUsage": "Token Usage", "tokenUsage": "Token Usage",
"feedback": "Feedback", "feedback": "Feedback",
"filterPlaceholder": "Filter", "filterPlaceholder": "Filter",
"none": "None" "none": "None",
"positiveFeedback": "Positive Feedback",
"negativeFeedback": "Negative Feedback"
}, },
"logs": { "logs": {
"label": "Logs", "label": "Logs",
@@ -93,7 +95,12 @@
"tableHeader": "API generated / chatbot conversations" "tableHeader": "API generated / chatbot conversations"
}, },
"tools": { "tools": {
"label": "Tools" "label": "Tools",
"searchPlaceholder": "Search...",
"addTool": "Add Tool",
"noToolsAlt": "No tools found",
"noToolsFound": "No tools found",
"selectToolSetup": "Select a tool to set up"
} }
}, },
"modals": { "modals": {
@@ -150,6 +157,24 @@
"note": "Source document, personal information and further conversation will remain private", "note": "Source document, personal information and further conversation will remain private",
"create": "Create", "create": "Create",
"option": "Allow users to prompt further" "option": "Allow users to prompt further"
},
"configTool": {
"title": "Tool Config",
"type": "Type",
"apiKeyLabel": "API Key / OAuth",
"apiKeyPlaceholder": "Enter API Key / OAuth",
"addButton": "Add Tool",
"closeButton": "Close"
},
"prompts": {
"addPrompt": "Add Prompt",
"addDescription": "Add your custom prompt and save it to DocsGPT",
"editPrompt": "Edit Prompt",
"editDescription": "Edit your custom prompt and save it to DocsGPT",
"promptName": "Prompt Name",
"promptText": "Prompt Text",
"save": "Save",
"nameExists": "Name already exists"
} }
}, },
"sharedConv": { "sharedConv": {
@@ -162,5 +187,13 @@
"delete": "Delete", "delete": "Delete",
"rename": "Rename", "rename": "Rename",
"deleteWarning": "Are you sure you want to delete this conversation?" "deleteWarning": "Are you sure you want to delete this conversation?"
},
"pagination": {
"rowsPerPage": "Rows per page",
"pageOf": "Page {{currentPage}} of {{totalPages}}",
"firstPage": "First page",
"previousPage": "Previous page",
"nextPage": "Next page",
"lastPage": "Last page"
} }
} }
+19 -1
View File
@@ -83,7 +83,9 @@
"tokenUsage": "Uso de Tokens", "tokenUsage": "Uso de Tokens",
"feedback": "Retroalimentación", "feedback": "Retroalimentación",
"filterPlaceholder": "Filtrar", "filterPlaceholder": "Filtrar",
"none": "Ninguno" "none": "Ninguno",
"positiveFeedback": "Retroalimentación Positiva",
"negativeFeedback": "Retroalimentación Negativa"
}, },
"logs": { "logs": {
"label": "Registros", "label": "Registros",
@@ -150,6 +152,14 @@
"note": "El documento original, la información personal y las conversaciones posteriores permanecerán privadas", "note": "El documento original, la información personal y las conversaciones posteriores permanecerán privadas",
"create": "Crear", "create": "Crear",
"option": "Permitir a los usuarios realizar más consultas" "option": "Permitir a los usuarios realizar más consultas"
},
"configTool": {
"title": "Configuración de la Herramienta",
"type": "Tipo",
"apiKeyLabel": "Clave API / OAuth",
"apiKeyPlaceholder": "Ingrese la Clave API / OAuth",
"addButton": "Agregar Herramienta",
"closeButton": "Cerrar"
} }
}, },
"sharedConv": { "sharedConv": {
@@ -162,5 +172,13 @@
"delete": "Eliminar", "delete": "Eliminar",
"rename": "Renombrar", "rename": "Renombrar",
"deleteWarning": "¿Está seguro de que desea eliminar esta conversación?" "deleteWarning": "¿Está seguro de que desea eliminar esta conversación?"
},
"pagination": {
"rowsPerPage": "Filas por página",
"pageOf": "Página {{currentPage}} de {{totalPages}}",
"firstPage": "Primera página",
"previousPage": "Página anterior",
"nextPage": "Página siguiente",
"lastPage": "Última página"
} }
} }
+43 -10
View File
@@ -58,15 +58,15 @@
"date": "ベクトル日付", "date": "ベクトル日付",
"type": "タイプ", "type": "タイプ",
"tokenUsage": "トークン使用量", "tokenUsage": "トークン使用量",
"noData": "既存のドキュメントはありません" "noData": "既存のドキュメントがありません"
}, },
"apiKeys": { "apiKeys": {
"label": "チャットボット", "label": "APIキー",
"name": "名前", "name": "名前",
"key": "APIキー", "key": "APIキー",
"sourceDoc": "ソースドキュメント", "sourceDoc": "ソースドキュメント",
"createNew": "新規作成", "createNew": "新規作成",
"noData": "既存のチャットボットはありません" "noData": "既存のAPIキーがありません"
}, },
"analytics": { "analytics": {
"label": "分析", "label": "分析",
@@ -74,26 +74,33 @@
"selectChatbot": "チャットボットを選択", "selectChatbot": "チャットボットを選択",
"filterOptions": { "filterOptions": {
"hour": "時間", "hour": "時間",
"last24Hours": "24時間", "last24Hours": "過去24時間",
"last7Days": "7日間", "last7Days": "過去7日間",
"last15Days": "15日間", "last15Days": "過去15日間",
"last30Days": "30日間" "last30Days": "過去30日間"
}, },
"messages": "メッセージ", "messages": "メッセージ",
"tokenUsage": "トークン使用量", "tokenUsage": "トークン使用量",
"feedback": "フィードバック", "feedback": "フィードバック",
"filterPlaceholder": "フィルター", "filterPlaceholder": "フィルター",
"none": "なし" "none": "なし",
"positiveFeedback": "肯定的なフィードバック",
"negativeFeedback": "否定的なフィードバック"
}, },
"logs": { "logs": {
"label": "ログ", "label": "ログ",
"filterByChatbot": "チャットボットでフィルター", "filterByChatbot": "チャットボットでフィルター",
"selectChatbot": "チャットボットを選択", "selectChatbot": "チャットボットを選択",
"none": "なし", "none": "なし",
"tableHeader": "API生成/チャットボットの会話" "tableHeader": "API生成 / チャットボットの会話"
}, },
"tools": { "tools": {
"label": "ツール" "label": "ツール",
"searchPlaceholder": "検索...",
"addTool": "ツールを追加",
"noToolsAlt": "ツールが見つかりません",
"noToolsFound": "ツールが見つかりません",
"selectToolSetup": "設定するツールを選択してください"
} }
}, },
"modals": { "modals": {
@@ -150,6 +157,24 @@
"note": "ソースドキュメント、個人情報、および以降の会話は非公開のままになります", "note": "ソースドキュメント、個人情報、および以降の会話は非公開のままになります",
"create": "作成", "create": "作成",
"option": "ユーザーがより多くのクエリを実行できるようにします。" "option": "ユーザーがより多くのクエリを実行できるようにします。"
},
"configTool": {
"title": "ツール設定",
"type": "タイプ",
"apiKeyLabel": "APIキー / OAuth",
"apiKeyPlaceholder": "APIキー / OAuthを入力してください",
"addButton": "ツールを追加",
"closeButton": "閉じる"
},
"prompts": {
"addPrompt": "プロンプトを追加",
"addDescription": "カスタムプロンプトを追加してDocsGPTに保存",
"editPrompt": "プロンプトを編集",
"editDescription": "カスタムプロンプトを編集してDocsGPTに保存",
"promptName": "プロンプト名",
"promptText": "プロンプトテキスト",
"save": "保存",
"nameExists": "名前が既に存在します"
} }
}, },
"sharedConv": { "sharedConv": {
@@ -162,5 +187,13 @@
"delete": "削除", "delete": "削除",
"rename": "名前変更", "rename": "名前変更",
"deleteWarning": "この会話を削除してもよろしいですか?" "deleteWarning": "この会話を削除してもよろしいですか?"
},
"pagination": {
"rowsPerPage": "1ページあたりの行数",
"pageOf": "ページ {{currentPage}} / {{totalPages}}",
"firstPage": "最初のページ",
"previousPage": "前のページ",
"nextPage": "次のページ",
"lastPage": "最後のページ"
} }
} }
+66 -30
View File
@@ -10,6 +10,9 @@
"sourceDocs": "Источник", "sourceDocs": "Источник",
"none": "Нет", "none": "Нет",
"cancel": "Отмена", "cancel": "Отмена",
"help": "Помощь",
"emailUs": "Напишите нам",
"documentation": "Документация",
"demo": [ "demo": [
{ {
"header": "Узнайте о DocsGPT", "header": "Узнайте о DocsGPT",
@@ -34,7 +37,7 @@
"label": "Общие", "label": "Общие",
"selectTheme": "Выбрать тему", "selectTheme": "Выбрать тему",
"light": "Светлая", "light": "Светлая",
"dark": "Темная", "dark": "Тёмная",
"selectLanguage": "Выбрать язык", "selectLanguage": "Выбрать язык",
"chunks": "Обработанные фрагменты на запрос", "chunks": "Обработанные фрагменты на запрос",
"prompt": "Активная подсказка", "prompt": "Активная подсказка",
@@ -47,7 +50,7 @@
"medium": "Средний", "medium": "Средний",
"high": "Высокий", "high": "Высокий",
"unlimited": "Без ограничений", "unlimited": "Без ограничений",
"default": "по умолчанию" "default": "По умолчанию"
}, },
"documents": { "documents": {
"label": "Документы", "label": "Документы",
@@ -58,12 +61,12 @@
"noData": "Нет существующих документов" "noData": "Нет существующих документов"
}, },
"apiKeys": { "apiKeys": {
"label": "Чат-боты", "label": "API ключи",
"name": "Название", "name": "Название",
"key": "Ключ API", "key": "API ключ",
"sourceDoc": "Исходный документ", "sourceDoc": "Источник документа",
"createNew": "Создать новый", "createNew": "Создать новый",
"noData": "Нет существующих чат-ботов" "noData": "Нет существующих API ключей"
}, },
"analytics": { "analytics": {
"label": "Аналитика", "label": "Аналитика",
@@ -71,52 +74,59 @@
"selectChatbot": "Выбрать чат-бота", "selectChatbot": "Выбрать чат-бота",
"filterOptions": { "filterOptions": {
"hour": "Час", "hour": "Час",
"last24Hours": "24 часа", "last24Hours": "Последние 24 часа",
"last7Days": "7 дней", "last7Days": "Последние 7 дней",
"last15Days": "15 дней", "last15Days": "Последние 15 дней",
"last30Days": "30 дней" "last30Days": "Последние 30 дней"
}, },
"messages": "Сообщения", "messages": "Сообщения",
"tokenUsage": "Использование токенов", "tokenUsage": "Использование токена",
"feedback": "Обратная связь", "feedback": "Обратная связь",
"filterPlaceholder": "Фильтр", "filterPlaceholder": "Фильтр",
"none": "Нет" "none": "Нет",
"positiveFeedback": "Положительная обратная связь",
"negativeFeedback": "Отрицательная обратная связь"
}, },
"logs": { "logs": {
"label": "Журналы", "label": "Журналы",
"filterByChatbot": "Фильтровать по чат-боту", "filterByChatbot": "Фильтровать по чат-боту",
"selectChatbot": "Выбрать чат-бота", "selectChatbot": "Выбрать чат-бота",
"none": "Нет", "none": "Нет",
"tableHeader": "Сгенерированные API / разговоры с чат-ботом" "tableHeader": "API сгенерировано / разговоры с чат-ботом"
}, },
"tools": { "tools": {
"label": "Инструменты" "label": "Инструменты",
"searchPlaceholder": "Поиск...",
"addTool": "Добавить инструмент",
"noToolsAlt": "Инструменты не найдены",
"noToolsFound": "Инструменты не найдены",
"selectToolSetup": "Выберите инструмент для настройки"
} }
}, },
"modals": { "modals": {
"uploadDoc": { "uploadDoc": {
"label": "Загрузить новую документацию", "label": "Загрузить новый документ",
"select": "Выберите способ загрузки документа в DocsGPT", "select": "Выберите способ загрузки документа в DocsGPT",
"file": "Загрузить с устройства", "file": "Загрузить с устройства",
"back": "Назад", "back": "Назад",
"wait": "Пожалуйста, подождите ...", "wait": "Пожалуйста, подождите...",
"remote": "Собрать с веб-сайта", "remote": "Собрать с веб-сайта",
"start": "Начать чат", "start": "Начать чат",
"name": "Имя", "name": "Имя",
"choose": "Выбрать файлы", "choose": "Выбрать файлы",
"info": "Загрузите .pdf, .txt, .rst, .csv, .xlsx, .docx, .md, .html, .epub, .json, .pptx, .zip с ограничением до 25 МБ", "info": "Пожалуйста, загрузите файлы .pdf, .txt, .rst, .csv, .xlsx, .docx, .md, .html, .epub, .json, .pptx, .zip размером до 25 МБ",
"uploadedFiles": "Загруженные файлы", "uploadedFiles": "Загруженные файлы",
"cancel": "Отмена", "cancel": "Отмена",
"train": "Обучение", "train": "Обучение",
"link": "Ссылка", "link": "Ссылка",
"urlLink": "URL-ссылка", "urlLink": "URL-ссылка",
"repoUrl": "URL-адрес репозитория", "repoUrl": "URL репозитория",
"reddit": { "reddit": {
"id": "ID клиента", "id": "ID клиента",
"secret": "Секрет клиента", "secret": "Секрет клиента",
"agent": "Агент пользователя", "agent": "Пользовательский агент",
"searchQueries": "Поисковые запросы", "searchQueries": "Поисковые запросы",
"numberOfPosts": "Количество постов" "numberOfPosts": "Количество сообщений"
}, },
"drag": { "drag": {
"title": "Загрузить исходный файл", "title": "Загрузить исходный файл",
@@ -124,16 +134,16 @@
} }
}, },
"createAPIKey": { "createAPIKey": {
"label": "Создать новый ключ API", "label": "Создать новый API ключ",
"apiKeyName": "Название ключа API", "apiKeyName": "Название API ключа",
"chunks": "Обработанные фрагменты на запрос", "chunks": "Обработанные фрагменты на запрос",
"prompt": "Выбрать активный запрос", "prompt": "Выбрать активную подсказку",
"sourceDoc": "Исходный документ", "sourceDoc": "Источник документа",
"create": "Создать" "create": "Создать"
}, },
"saveKey": { "saveKey": {
"note": "Пожалуйста, сохраните свой ключ", "note": "Пожалуйста, сохраните ваш ключ",
"disclaimer": "Это единственный раз, когда будет показан ваш ключ", "disclaimer": "Ваш ключ будет показан только один раз.",
"copy": "Копировать", "copy": "Копировать",
"copied": "Скопировано", "copied": "Скопировано",
"confirm": "Я сохранил ключ" "confirm": "Я сохранил ключ"
@@ -143,21 +153,47 @@
"delete": "Удалить" "delete": "Удалить"
}, },
"shareConv": { "shareConv": {
"label": "Создать публичную страницу для общего доступа", "label": "Создать публичную страницу для совместного использования",
"note": "Исходный документ, личная информация и дальнейший разговор останутся конфиденциальными", "note": "Исходный документ, личная информация и последующие разговоры останутся приватными",
"create": "Создать", "create": "Создать",
"option": "Разрешить пользователям делать дополнительные запросы" "option": "Позволить пользователям делать дополнительные запросы."
},
"configTool": {
"title": "Настройка инструмента",
"type": "Тип",
"apiKeyLabel": "API ключ / OAuth",
"apiKeyPlaceholder": "Введите API ключ / OAuth",
"addButton": "Добавить инструмент",
"closeButton": "Закрыть"
},
"prompts": {
"addPrompt": "Добавить подсказку",
"addDescription": "Добавить вашу пользовательскую подсказку и сохранить её в DocsGPT",
"editPrompt": "Редактировать подсказку",
"editDescription": "Редактировать вашу пользовательскую подсказку и сохранить её в DocsGPT",
"promptName": "Название подсказки",
"promptText": "Текст подсказки",
"save": "Сохранить",
"nameExists": "Название уже существует"
} }
}, },
"sharedConv": { "sharedConv": {
"subtitle": "Создано с помощью", "subtitle": "Создано с помощью",
"button": "Начать работу с DocsGPT", "button": "Начать работу с DocsGPT",
"meta": "DocsGPT использует GenAI, пожалуйста, проверяйте важную информацию, используя источники" "meta": "DocsGPT использует GenAI, пожалуйста, проверьте важную информацию, используя источники."
}, },
"convTile": { "convTile": {
"share": "Поделиться", "share": "Поделиться",
"delete": "Удалить", "delete": "Удалить",
"rename": "Переименовать", "rename": "Переименовать",
"deleteWarning": "Вы уверены, что хотите удалить этот разговор?" "deleteWarning": "Вы уверены, что хотите удалить этот разговор?"
},
"pagination": {
"rowsPerPage": "Строк на странице",
"pageOf": "Страница {{currentPage}} из {{totalPages}}",
"firstPage": "Первая страница",
"previousPage": "Предыдущая страница",
"nextPage": "Следующая страница",
"lastPage": "Последняя страница"
} }
} }
+48 -7
View File
@@ -57,14 +57,16 @@
"name": "文件名稱", "name": "文件名稱",
"date": "向量日期", "date": "向量日期",
"type": "類型", "type": "類型",
"tokenUsage": "Token 使用量" "tokenUsage": "Token 使用量",
"noData": "沒有現有的文件"
}, },
"apiKeys": { "apiKeys": {
"label": "API 金鑰", "label": "聊天機器人",
"name": "名稱", "name": "名稱",
"key": "API 金鑰", "key": "API 金鑰",
"sourceDoc": "來源文件", "sourceDoc": "來源文件",
"createNew": "新增" "createNew": "新增",
"noData": "沒有現有的聊天機器人"
}, },
"analytics": { "analytics": {
"label": "分析", "label": "分析",
@@ -81,7 +83,9 @@
"tokenUsage": "Token 使用量", "tokenUsage": "Token 使用量",
"feedback": "回饋", "feedback": "回饋",
"filterPlaceholder": "篩選", "filterPlaceholder": "篩選",
"none": "無" "none": "無",
"positiveFeedback": "正向回饋",
"negativeFeedback": "負向回饋"
}, },
"logs": { "logs": {
"label": "日誌", "label": "日誌",
@@ -91,22 +95,32 @@
"tableHeader": "API 生成 / 聊天機器人會話" "tableHeader": "API 生成 / 聊天機器人會話"
}, },
"tools": { "tools": {
"label": "工具" "label": "工具",
"searchPlaceholder": "搜尋...",
"addTool": "新增工具",
"noToolsAlt": "找不到工具",
"noToolsFound": "找不到工具",
"selectToolSetup": "選擇要設定的工具"
} }
}, },
"modals": { "modals": {
"uploadDoc": { "uploadDoc": {
"label": "上傳新文件", "label": "上傳新文件",
"select": "選擇如何將文件上傳到 DocsGPT",
"file": "從檔案", "file": "從檔案",
"remote": "遠端", "remote": "遠端",
"back": "返回",
"wait": "請稍候...",
"start": "開始對話",
"name": "名稱", "name": "名稱",
"choose": "選擇檔案", "choose": "選擇檔案",
"info": "請上傳 .pdf, .txt, .rst, .docx, .md, .json, .pptx, .zip 檔案,大小限制為 25MB", "info": "請上傳 .pdf, .txt, .rst, .csv, .xlsx, .docx, .md, .html, .epub, .json, .pptx, .zip 檔案,大小限制為 25MB",
"uploadedFiles": "已上傳的檔案", "uploadedFiles": "已上傳的檔案",
"cancel": "取消", "cancel": "取消",
"train": "訓練", "train": "訓練",
"link": "連結", "link": "連結",
"urlLink": "URL 連結", "urlLink": "URL 連結",
"repoUrl": "儲存庫 URL",
"reddit": { "reddit": {
"id": "用戶端 ID", "id": "用戶端 ID",
"secret": "用戶端金鑰", "secret": "用戶端金鑰",
@@ -141,7 +155,26 @@
"shareConv": { "shareConv": {
"label": "建立公開頁面以分享", "label": "建立公開頁面以分享",
"note": "來源文件、個人資訊和後續對話將保持私密", "note": "來源文件、個人資訊和後續對話將保持私密",
"create": "建立" "create": "建立",
"option": "允許使用者進行更多查詢"
},
"configTool": {
"title": "工具設定",
"type": "類型",
"apiKeyLabel": "API 金鑰 / OAuth",
"apiKeyPlaceholder": "輸入 API 金鑰 / OAuth",
"addButton": "新增工具",
"closeButton": "關閉"
},
"prompts": {
"addPrompt": "新增提示",
"addDescription": "新增自定義提示並儲存到 DocsGPT",
"editPrompt": "編輯提示",
"editDescription": "編輯自定義提示並儲存到 DocsGPT",
"promptName": "提示名稱",
"promptText": "提示文字",
"save": "儲存",
"nameExists": "名稱已存在"
} }
}, },
"sharedConv": { "sharedConv": {
@@ -154,5 +187,13 @@
"delete": "刪除", "delete": "刪除",
"rename": "重新命名", "rename": "重新命名",
"deleteWarning": "您確定要刪除這個對話嗎?" "deleteWarning": "您確定要刪除這個對話嗎?"
},
"pagination": {
"rowsPerPage": "每頁行數",
"pageOf": "第 {{currentPage}} 頁,共 {{totalPages}} 頁",
"firstPage": "第一頁",
"previousPage": "上一頁",
"nextPage": "下一頁",
"lastPage": "最後一頁"
} }
} }
+35 -2
View File
@@ -83,7 +83,9 @@
"tokenUsage": "令牌使用", "tokenUsage": "令牌使用",
"feedback": "反馈", "feedback": "反馈",
"filterPlaceholder": "筛选", "filterPlaceholder": "筛选",
"none": "无" "none": "无",
"positiveFeedback": "正向反馈",
"negativeFeedback": "负向反馈"
}, },
"logs": { "logs": {
"label": "日志", "label": "日志",
@@ -93,7 +95,12 @@
"tableHeader": "API 生成 / 聊天机器人会话" "tableHeader": "API 生成 / 聊天机器人会话"
}, },
"tools": { "tools": {
"label": "工具" "label": "工具",
"searchPlaceholder": "搜索...",
"addTool": "添加工具",
"noToolsAlt": "未找到工具",
"noToolsFound": "未找到工具",
"selectToolSetup": "选择要设置的工具"
} }
}, },
"modals": { "modals": {
@@ -150,6 +157,24 @@
"note": "源文档、个人信息和后续对话将保持私密", "note": "源文档、个人信息和后续对话将保持私密",
"create": "创建", "create": "创建",
"option": "允许用户进行更多查询。" "option": "允许用户进行更多查询。"
},
"configTool": {
"title": "工具配置",
"type": "类型",
"apiKeyLabel": "API 密钥 / OAuth",
"apiKeyPlaceholder": "输入 API 密钥 / OAuth",
"addButton": "添加工具",
"closeButton": "关闭"
},
"prompts": {
"addPrompt": "添加提示",
"addDescription": "添加自定义提示并保存到 DocsGPT",
"editPrompt": "编辑提示",
"editDescription": "编辑自定义提示并保存到 DocsGPT",
"promptName": "提示名称",
"promptText": "提示文本",
"save": "保存",
"nameExists": "名称已存在"
} }
}, },
"sharedConv": { "sharedConv": {
@@ -162,5 +187,13 @@
"delete": "删除", "delete": "删除",
"rename": "重命名", "rename": "重命名",
"deleteWarning": "您确定要删除此对话吗?" "deleteWarning": "您确定要删除此对话吗?"
},
"pagination": {
"rowsPerPage": "每页行数",
"pageOf": "第 {{currentPage}} 页,共 {{totalPages}} 页",
"firstPage": "第一页",
"previousPage": "上一页",
"nextPage": "下一页",
"lastPage": "最后一页"
} }
} }
+9 -6
View File
@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next';
import Exit from '../assets/exit.svg'; import Exit from '../assets/exit.svg';
import Input from '../components/Input'; import Input from '../components/Input';
@@ -17,6 +18,7 @@ export default function ConfigToolModal({
tool: AvailableTool | null; tool: AvailableTool | null;
getUserTools: () => void; getUserTools: () => void;
}) { }) {
const { t } = useTranslation();
const [authKey, setAuthKey] = React.useState<string>(''); const [authKey, setAuthKey] = React.useState<string>('');
const handleAddTool = (tool: AvailableTool) => { const handleAddTool = (tool: AvailableTool) => {
@@ -52,21 +54,22 @@ export default function ConfigToolModal({
</button> </button>
<div className="p-6"> <div className="p-6">
<h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3"> <h2 className="font-semibold text-xl text-jet dark:text-bright-gray px-3">
Tool Config {t('modals.configTool.title')}
</h2> </h2>
<p className="mt-5 text-sm text-gray-600 dark:text-gray-400 px-3"> <p className="mt-5 text-sm text-gray-600 dark:text-gray-400 px-3">
Type: <span className="font-semibold">{tool?.name} </span> {t('modals.configTool.type')}:{' '}
<span className="font-semibold">{tool?.name} </span>
</p> </p>
<div className="mt-6 relative px-3"> <div className="mt-6 relative px-3">
<span className="absolute left-5 -top-2 bg-white px-2 text-xs text-gray-4000 dark:bg-[#26272E] dark:text-silver"> <span className="absolute left-5 -top-2 bg-white px-2 text-xs text-gray-4000 dark:bg-[#26272E] dark:text-silver">
API Key / Oauth {t('modals.configTool.apiKeyLabel')}
</span> </span>
<Input <Input
type="text" type="text"
value={authKey} value={authKey}
onChange={(e) => setAuthKey(e.target.value)} onChange={(e) => setAuthKey(e.target.value)}
borderVariant="thin" borderVariant="thin"
placeholder="Enter API Key / Oauth" placeholder={t('modals.configTool.apiKeyPlaceholder')}
></Input> ></Input>
</div> </div>
<div className="mt-8 flex flex-row-reverse gap-1 px-3"> <div className="mt-8 flex flex-row-reverse gap-1 px-3">
@@ -76,7 +79,7 @@ export default function ConfigToolModal({
}} }}
className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:bg-[#6F3FD1]" className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:bg-[#6F3FD1]"
> >
Add Tool {t('modals.configTool.addButton')}
</button> </button>
<button <button
onClick={() => { onClick={() => {
@@ -84,7 +87,7 @@ export default function ConfigToolModal({
}} }}
className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50" className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50"
> >
Close {t('modals.configTool.closeButton')}
</button> </button>
</div> </div>
</div> </div>
+11 -5
View File
@@ -101,11 +101,17 @@ export const ShareConversationModal = ({
return ( return (
<WrapperModal close={close}> <WrapperModal close={close}>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<h2 className="text-xl font-medium">{t('modals.shareConv.label')}</h2> <h2 className="text-xl font-medium text-eerie-black dark:text-white">
<p className="text-sm">{t('modals.shareConv.note')}</p> {t('modals.shareConv.label')}
</h2>
<p className="text-sm text-eerie-black dark:text-white">
{t('modals.shareConv.note')}
</p>
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-lg">{t('modals.shareConv.option')}</span> <span className="text-lg text-eerie-black dark:text-white">
<label className=" cursor-pointer select-none items-center"> {t('modals.shareConv.option')}
</span>
<label className="cursor-pointer select-none items-center">
<div className="relative"> <div className="relative">
<input <input
type="checkbox" type="checkbox"
@@ -143,7 +149,7 @@ export const ShareConversationModal = ({
</div> </div>
)} )}
<div className="flex items-baseline justify-between gap-2"> <div className="flex items-baseline justify-between gap-2">
<span className="no-scrollbar w-full overflow-x-auto whitespace-nowrap rounded-full border-2 py-3 px-4"> <span className="no-scrollbar w-full overflow-x-auto whitespace-nowrap rounded-full border-2 py-3 px-4 text-eerie-black dark:text-white">
{`${domain}/share/${identifier ?? '....'}`} {`${domain}/share/${identifier ?? '....'}`}
</span> </span>
{status === 'fetched' ? ( {status === 'fetched' ? (
+25 -14
View File
@@ -2,6 +2,7 @@ import { ActiveState } from '../models/misc';
import Exit from '../assets/exit.svg'; import Exit from '../assets/exit.svg';
import Input from '../components/Input'; import Input from '../components/Input';
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next';
function AddPrompt({ function AddPrompt({
setModalState, setModalState,
@@ -20,6 +21,8 @@ function AddPrompt({
setNewPromptContent: (content: string) => void; setNewPromptContent: (content: string) => void;
disableSave: boolean; disableSave: boolean;
}) { }) {
const { t } = useTranslation();
return ( return (
<div className="relative"> <div className="relative">
<button <button
@@ -34,14 +37,14 @@ function AddPrompt({
</button> </button>
<div className="p-8"> <div className="p-8">
<p className="mb-1 text-xl text-jet dark:text-bright-gray"> <p className="mb-1 text-xl text-jet dark:text-bright-gray">
Add Prompt {t('modals.prompts.addPrompt')}
</p> </p>
<p className="mb-7 text-xs text-[#747474] dark:text-[#7F7F82]"> <p className="mb-7 text-xs text-[#747474] dark:text-[#7F7F82]">
Add your custom prompt and save it to DocsGPT {t('modals.prompts.addDescription')}
</p> </p>
<div> <div>
<Input <Input
placeholder="Prompt Name" placeholder={t('modals.prompts.promptName')}
type="text" type="text"
className="h-10 rounded-lg" className="h-10 rounded-lg"
value={newPromptName} value={newPromptName}
@@ -49,12 +52,12 @@ function AddPrompt({
/> />
<div className="relative bottom-12 left-3 mt-[-3.00px]"> <div className="relative bottom-12 left-3 mt-[-3.00px]">
<span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver"> <span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver">
Prompt Name {t('modals.prompts.promptName')}
</span> </span>
</div> </div>
<div className="relative top-[7px] left-3"> <div className="relative top-[7px] left-3">
<span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver"> <span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver">
Prompt Text {t('modals.prompts.promptText')}
</span> </span>
</div> </div>
<textarea <textarea
@@ -68,9 +71,11 @@ function AddPrompt({
onClick={handleAddPrompt} onClick={handleAddPrompt}
className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:opacity-90" className="rounded-3xl bg-purple-30 px-5 py-2 text-sm text-white transition-all hover:opacity-90"
disabled={disableSave} disabled={disableSave}
title={disableSave && newPromptName ? 'Name already exists' : ''} title={
disableSave && newPromptName ? t('modals.prompts.nameExists') : ''
}
> >
Save {t('modals.prompts.save')}
</button> </button>
</div> </div>
</div> </div>
@@ -97,6 +102,8 @@ function EditPrompt({
currentPromptEdit: { name: string; id: string; type: string }; currentPromptEdit: { name: string; id: string; type: string };
disableSave: boolean; disableSave: boolean;
}) { }) {
const { t } = useTranslation();
return ( return (
<div className="relative"> <div className="relative">
<button <button
@@ -109,14 +116,14 @@ function EditPrompt({
</button> </button>
<div className="p-8"> <div className="p-8">
<p className="mb-1 text-xl text-jet dark:text-bright-gray"> <p className="mb-1 text-xl text-jet dark:text-bright-gray">
Edit Prompt {t('modals.prompts.editPrompt')}
</p> </p>
<p className="mb-7 text-xs text-[#747474] dark:text-[#7F7F82]"> <p className="mb-7 text-xs text-[#747474] dark:text-[#7F7F82]">
Edit your custom prompt and save it to DocsGPT {t('modals.prompts.editDescription')}
</p> </p>
<div> <div>
<Input <Input
placeholder="Prompt Name" placeholder={t('modals.prompts.promptName')}
type="text" type="text"
className="h-10 rounded-lg" className="h-10 rounded-lg"
value={editPromptName} value={editPromptName}
@@ -124,12 +131,12 @@ function EditPrompt({
></Input> ></Input>
<div className="relative bottom-12 left-3 mt-[-3.00px]"> <div className="relative bottom-12 left-3 mt-[-3.00px]">
<span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver"> <span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver">
Prompt Name {t('modals.prompts.promptName')}
</span> </span>
</div> </div>
<div className="relative top-[7px] left-3"> <div className="relative top-[7px] left-3">
<span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver"> <span className="bg-white px-1 text-xs text-silver dark:bg-outer-space dark:text-silver">
Prompt Text {t('modals.prompts.promptText')}
</span> </span>
</div> </div>
<textarea <textarea
@@ -150,9 +157,13 @@ function EditPrompt({
handleEditPrompt(currentPromptEdit.id, currentPromptEdit.type); handleEditPrompt(currentPromptEdit.id, currentPromptEdit.type);
}} }}
disabled={currentPromptEdit.type === 'public' || disableSave} disabled={currentPromptEdit.type === 'public' || disableSave}
title={disableSave && editPromptName ? 'Name already exists' : ''} title={
disableSave && editPromptName
? t('modals.prompts.nameExists')
: ''
}
> >
Save {t('modals.prompts.save')}
</button> </button>
</div> </div>
</div> </div>
+12 -3
View File
@@ -69,15 +69,24 @@ export default function Analytics() {
const [messagesFilter, setMessagesFilter] = useState<{ const [messagesFilter, setMessagesFilter] = useState<{
label: string; label: string;
value: string; value: string;
}>({ label: '30 Days', value: 'last_30_days' }); }>({
label: t('settings.analytics.filterOptions.last30Days'),
value: 'last_30_days',
});
const [tokenUsageFilter, setTokenUsageFilter] = useState<{ const [tokenUsageFilter, setTokenUsageFilter] = useState<{
label: string; label: string;
value: string; value: string;
}>({ label: '30 Days', value: 'last_30_days' }); }>({
label: t('settings.analytics.filterOptions.last30Days'),
value: 'last_30_days',
});
const [feedbackFilter, setFeedbackFilter] = useState<{ const [feedbackFilter, setFeedbackFilter] = useState<{
label: string; label: string;
value: string; value: string;
}>({ label: '30 Days', value: 'last_30_days' }); }>({
label: t('settings.analytics.filterOptions.last30Days'),
value: 'last_30_days',
});
const [loadingMessages, setLoadingMessages] = useState(true); const [loadingMessages, setLoadingMessages] = useState(true);
const [loadingTokens, setLoadingTokens] = useState(true); const [loadingTokens, setLoadingTokens] = useState(true);
+11 -6
View File
@@ -19,9 +19,12 @@ import Prompts from './Prompts';
export default function General() { export default function General() {
const { const {
t, t,
i18n: { changeLanguage, language }, i18n: { changeLanguage },
} = useTranslation(); } = useTranslation();
const themes = ['Light', 'Dark']; const themes = [
{ value: 'Light', label: t('settings.general.light') },
{ value: 'Dark', label: t('settings.general.dark') },
];
const languageOptions = [ const languageOptions = [
{ {
@@ -104,10 +107,12 @@ export default function General() {
</p> </p>
<Dropdown <Dropdown
options={themes} options={themes}
selectedValue={selectedTheme} selectedValue={
onSelect={(option: string) => { themes.find((theme) => theme.value === selectedTheme) || null
setSelectedTheme(option); }
option !== selectedTheme && toggleTheme(); onSelect={(option: { value: string; label: string }) => {
setSelectedTheme(option.value);
option.value !== selectedTheme && toggleTheme();
}} }}
size="w-56" size="w-56"
rounded="3xl" rounded="3xl"
+7 -5
View File
@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { useTranslation } from 'react-i18next';
import userService from '../api/services/userService'; import userService from '../api/services/userService';
import CogwheelIcon from '../assets/cogwheel.svg'; import CogwheelIcon from '../assets/cogwheel.svg';
@@ -12,6 +13,7 @@ import ToolConfig from './ToolConfig';
import { UserTool } from './types'; import { UserTool } from './types';
export default function Tools() { export default function Tools() {
const { t } = useTranslation();
const [isDarkTheme] = useDarkTheme(); const [isDarkTheme] = useDarkTheme();
const [searchTerm, setSearchTerm] = React.useState(''); const [searchTerm, setSearchTerm] = React.useState('');
const [addToolModalState, setAddToolModalState] = const [addToolModalState, setAddToolModalState] =
@@ -72,7 +74,7 @@ export default function Tools() {
<div className="p-1"> <div className="p-1">
<Input <Input
maxLength={256} maxLength={256}
placeholder="Search..." placeholder={t('settings.tools.searchPlaceholder')}
name="Document-search-input" name="Document-search-input"
type="text" type="text"
id="document-search-input" id="document-search-input"
@@ -86,7 +88,7 @@ export default function Tools() {
setAddToolModalState('ACTIVE'); setAddToolModalState('ACTIVE');
}} }}
> >
Add Tool {t('settings.tools.addTool')}
</button> </button>
</div> </div>
<div className="grid grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-2 lg:grid-cols-3 gap-6">
@@ -98,10 +100,10 @@ export default function Tools() {
<div className="mt-24 col-span-2 lg:col-span-3 text-center text-gray-500 dark:text-gray-400"> <div className="mt-24 col-span-2 lg:col-span-3 text-center text-gray-500 dark:text-gray-400">
<img <img
src={isDarkTheme ? NoFilesDarkIcon : NoFilesIcon} src={isDarkTheme ? NoFilesDarkIcon : NoFilesIcon}
alt="No tools found" alt={t('settings.tools.noToolsAlt')}
className="h-24 w-24 mx-auto mb-2" className="h-24 w-24 mx-auto mb-2"
/> />
No tools found {t('settings.tools.noToolsFound')}
</div> </div>
) : ( ) : (
userTools userTools
@@ -164,7 +166,7 @@ export default function Tools() {
</div> </div>
</div> </div>
<AddToolModal <AddToolModal
message="Select a tool to set up" message={t('settings.tools.selectToolSetup')}
modalState={addToolModalState} modalState={addToolModalState}
setModalState={setAddToolModalState} setModalState={setAddToolModalState}
getUserTools={getUserTools} getUserTools={getUserTools}
+52 -66
View File
@@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import userService from '../api/services/userService'; import userService from '../api/services/userService';
import ArrowLeft from '../assets/arrow-left.svg';
import FileUpload from '../assets/file_upload.svg'; import FileUpload from '../assets/file_upload.svg';
import WebsiteCollect from '../assets/website_collect.svg'; import WebsiteCollect from '../assets/website_collect.svg';
import Dropdown from '../components/Dropdown'; import Dropdown from '../components/Dropdown';
@@ -510,7 +509,7 @@ function Upload({
<div className="flex flex-col gap-1 mt-2"> <div className="flex flex-col gap-1 mt-2">
<div> <div>
<Input <Input
placeholder="Enter client ID" placeholder={t('modals.uploadDoc.reddit.id')}
type="text" type="text"
name="client_id" name="client_id"
value={redditData.client_id} value={redditData.client_id}
@@ -525,7 +524,7 @@ function Upload({
</div> </div>
<div> <div>
<Input <Input
placeholder="Enter client secret" placeholder={t('modals.uploadDoc.reddit.secret')}
type="text" type="text"
name="client_secret" name="client_secret"
value={redditData.client_secret} value={redditData.client_secret}
@@ -540,7 +539,7 @@ function Upload({
</div> </div>
<div> <div>
<Input <Input
placeholder="Enter user agent" placeholder={t('modals.uploadDoc.reddit.agent')}
type="text" type="text"
name="user_agent" name="user_agent"
value={redditData.user_agent} value={redditData.user_agent}
@@ -555,7 +554,7 @@ function Upload({
</div> </div>
<div> <div>
<Input <Input
placeholder="Enter search queries" placeholder={t('modals.uploadDoc.reddit.searchQueries')}
type="text" type="text"
name="search_queries" name="search_queries"
value={redditData.search_queries} value={redditData.search_queries}
@@ -570,7 +569,7 @@ function Upload({
</div> </div>
<div> <div>
<Input <Input
placeholder="Enter number of posts" placeholder={t('modals.uploadDoc.reddit.numberOfPosts')}
type="number" type="number"
name="number_posts" name="number_posts"
value={redditData.number_posts} value={redditData.number_posts}
@@ -587,70 +586,57 @@ function Upload({
)} )}
</> </>
)} )}
{activeTab && ( <div className="flex justify-between">
<div className="flex w-full justify-between flex-row-reverse"> {activeTab && (
{activeTab === 'file' ? (
<button
onClick={uploadFile}
className={`ml-2 cursor-pointer rounded-3xl bg-purple-30 text-sm text-white ${
files.length > 0 && docName.trim().length > 0
? 'hover:bg-[#6F3FD1]'
: 'bg-opacity-75 text-opacity-80'
} py-2 px-6`}
disabled={
(files.length === 0 || docName.trim().length === 0) &&
activeTab === 'file'
}
>
{t('modals.uploadDoc.train')}
</button>
) : (
<button
onClick={uploadRemote}
className={`ml-2 cursor-pointer rounded-3xl bg-purple-30 py-2 px-6 text-sm text-white hover:bg-[#6F3FD1] ${
urlName.trim().length === 0 ||
url.trim().length === 0 ||
(urlType.label === 'Reddit' &&
(redditData.client_id.length === 0 ||
redditData.client_secret.length === 0 ||
redditData.user_agent.length === 0 ||
redditData.search_queries.length === 0 ||
redditData.number_posts === 0)) ||
(urlType.label === 'GitHub' && repoUrl.trim().length === 0)
? 'bg-opacity-80 text-opacity-80'
: ''
}`}
disabled={
urlName.trim().length === 0 ||
url.trim().length === 0 ||
(urlType.label === 'Reddit' &&
(redditData.client_id.length === 0 ||
redditData.client_secret.length === 0 ||
redditData.user_agent.length === 0 ||
redditData.search_queries.length === 0 ||
redditData.number_posts === 0)) ||
(urlType.label === 'GitHub' && repoUrl.trim().length === 0)
}
>
{t('modals.uploadDoc.train')}
</button>
)}
<button <button
onClick={() => { onClick={() => setActiveTab(null)}
setDocName(''); className="rounded-3xl border border-purple-30 px-4 py-2 font-medium text-purple-30 hover:cursor-pointer dark:bg-purple-taupe dark:text-silver"
setfiles([]);
setActiveTab(null);
}}
className="cursor-pointer rounded-3xl px-5 py-2 text-sm font-medium hover:bg-gray-100 dark:bg-transparent dark:text-light-gray dark:hover:bg-[#767183]/50 flex items-center gap-1"
> >
<img
src={ArrowLeft}
className="w-[10px] h-[10px] dark:filter dark:invert"
/>
{t('modals.uploadDoc.back')} {t('modals.uploadDoc.back')}
</button> </button>
</div> )}
)} <button
onClick={() => {
if (activeTab === 'file') {
uploadFile();
} else {
uploadRemote();
}
}}
disabled={
(activeTab === 'file' && (!files.length || !docName)) ||
(activeTab === 'remote' &&
((urlType.label !== 'Reddit' &&
urlType.label !== 'GitHub' &&
(!url || !urlName)) ||
(urlType.label === 'GitHub' && !repoUrl) ||
(urlType.label === 'Reddit' &&
(!redditData.client_id ||
!redditData.client_secret ||
!redditData.user_agent ||
!redditData.search_queries ||
!redditData.number_posts))))
}
className={`rounded-3xl px-4 py-2 font-medium ${
(activeTab === 'file' && (!files.length || !docName)) ||
(activeTab === 'remote' &&
((urlType.label !== 'Reddit' &&
urlType.label !== 'GitHub' &&
(!url || !urlName)) ||
(urlType.label === 'GitHub' && !repoUrl) ||
(urlType.label === 'Reddit' &&
(!redditData.client_id ||
!redditData.client_secret ||
!redditData.user_agent ||
!redditData.search_queries ||
!redditData.number_posts))))
? 'cursor-not-allowed bg-gray-300 text-gray-500'
: 'cursor-pointer bg-purple-30 text-white hover:bg-purple-40'
}`}
>
{t('modals.uploadDoc.train')}
</button>
</div>
</div> </div>
); );
} }