✨ Добавлен русский язык + исправлены критические баги
🌍 Интернационализация: - Добавлен русский язык в i18n.ts (supportedLngs) - Русский пункт меню в NavBar.tsx (desktop + mobile) - Полная локализация страницы RobotCreate.tsx - Расширен ru.json: robotCreate (60+ ключей) + mainmenu 🐛 Исправления: - PostCSS баг в vite.config.js (css.postcss: false → { plugins: [] }) - Backend URL конфигурация (8081 вместо 8080) - API ключи теперь генерируются корректно 🔧 Конфигурация: - docker-compose.yml: host network mode - Dockerfile.frontend обновлен - Добавлены postcss конфиги ✅ Все сервисы работают: - Frontend: http://localhost:5174 - Backend: http://localhost:8081 - PostgreSQL: 5433 - MinIO: 9020/9021
This commit is contained in:
1
.postcssrc
Normal file
1
.postcssrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -8,15 +8,22 @@ COPY package*.json ./
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN npm install --legacy-peer-deps
|
RUN npm install --legacy-peer-deps
|
||||||
|
|
||||||
# Copy frontend source code and config
|
# Copy all configuration files first
|
||||||
COPY src ./src
|
|
||||||
COPY public ./public
|
|
||||||
COPY index.html ./
|
|
||||||
COPY vite.config.js ./
|
COPY vite.config.js ./
|
||||||
COPY tsconfig.json ./
|
COPY tsconfig.json ./
|
||||||
|
COPY index.html ./
|
||||||
|
COPY vite-env.d.ts ./
|
||||||
|
COPY postcss.config.mjs ./
|
||||||
|
|
||||||
|
# Copy frontend source code
|
||||||
|
COPY src ./src
|
||||||
|
COPY public ./public
|
||||||
|
|
||||||
|
# Build production bundle
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
# Expose the frontend port
|
# Expose the frontend port
|
||||||
EXPOSE ${FRONTEND_PORT:-5173}
|
EXPOSE ${FRONTEND_PORT:-5173}
|
||||||
|
|
||||||
# Start the frontend using the client script
|
# Serve static files using built-in Vite preview
|
||||||
CMD ["npm", "run", "client", "--", "--host"]
|
CMD ["npm", "run", "preview", "--", "--host", "0.0.0.0", "--port", "5173"]
|
||||||
@@ -7,7 +7,7 @@ services:
|
|||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
POSTGRES_DB: ${DB_NAME}
|
POSTGRES_DB: ${DB_NAME}
|
||||||
ports:
|
ports:
|
||||||
- "${DB_PORT:-5432}:${DB_PORT:-5432}"
|
- "5433:5432"
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
healthcheck:
|
healthcheck:
|
||||||
@@ -22,10 +22,10 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
|
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
|
||||||
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
|
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
|
||||||
command: server /data --console-address :${MINIO_CONSOLE_PORT:-9001}
|
command: server /data --console-address :9001
|
||||||
ports:
|
ports:
|
||||||
- "${MINIO_PORT:-9000}:${MINIO_PORT:-9000}" # API port
|
- "9020:9000" # API port
|
||||||
- "${MINIO_CONSOLE_PORT:-9001}:${MINIO_CONSOLE_PORT:-9001}" # WebUI port
|
- "9021:9001" # WebUI port
|
||||||
volumes:
|
volumes:
|
||||||
- minio_data:/data
|
- minio_data:/data
|
||||||
|
|
||||||
@@ -35,8 +35,7 @@ services:
|
|||||||
# dockerfile: Dockerfile.backend
|
# dockerfile: Dockerfile.backend
|
||||||
image: getmaxun/maxun-backend:latest
|
image: getmaxun/maxun-backend:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
network_mode: "host"
|
||||||
- "${BACKEND_PORT:-8080}:${BACKEND_PORT:-8080}"
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
environment:
|
||||||
BACKEND_URL: ${BACKEND_URL}
|
BACKEND_URL: ${BACKEND_URL}
|
||||||
@@ -65,12 +64,14 @@ services:
|
|||||||
# dockerfile: Dockerfile.frontend
|
# dockerfile: Dockerfile.frontend
|
||||||
image: getmaxun/maxun-frontend:latest
|
image: getmaxun/maxun-frontend:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
network_mode: "host"
|
||||||
- "${FRONTEND_PORT:-5173}:${FRONTEND_PORT:-5173}"
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
environment:
|
environment:
|
||||||
PUBLIC_URL: ${PUBLIC_URL}
|
PUBLIC_URL: http://localhost:5174
|
||||||
BACKEND_URL: ${BACKEND_URL}
|
BACKEND_URL: http://localhost:8081
|
||||||
|
VITE_BACKEND_URL: http://localhost:8081
|
||||||
|
VITE_PUBLIC_URL: http://localhost:5174
|
||||||
|
command: sh -c "npm run client"
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
|
|
||||||
@@ -79,11 +80,11 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: browser/Dockerfile
|
dockerfile: browser/Dockerfile
|
||||||
args:
|
args:
|
||||||
BROWSER_WS_PORT: ${BROWSER_WS_PORT:-3001}
|
BROWSER_WS_PORT: 3001
|
||||||
BROWSER_HEALTH_PORT: ${BROWSER_HEALTH_PORT:-3002}
|
BROWSER_HEALTH_PORT: 3002
|
||||||
ports:
|
ports:
|
||||||
- "${BROWSER_WS_PORT:-3001}:${BROWSER_WS_PORT:-3001}"
|
- "3011:3001"
|
||||||
- "${BROWSER_HEALTH_PORT:-3002}:${BROWSER_HEALTH_PORT:-3002}"
|
- "3012:3002"
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- DEBUG=pw:browser*
|
- DEBUG=pw:browser*
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"loglevel": "^1.8.0",
|
"loglevel": "^1.8.0",
|
||||||
"loglevel-plugin-remote": "^0.6.8",
|
"loglevel-plugin-remote": "^0.6.8",
|
||||||
"Dorod Parser-core": "^0.0.31",
|
"maxun-core": "^0.0.31",
|
||||||
"minio": "^8.0.1",
|
"minio": "^8.0.1",
|
||||||
"moment-timezone": "^0.5.45",
|
"moment-timezone": "^0.5.45",
|
||||||
"node-cron": "^3.0.3",
|
"node-cron": "^3.0.3",
|
||||||
|
|||||||
1
postcss.config.cjs
Normal file
1
postcss.config.cjs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module.exports = {};
|
||||||
@@ -55,6 +55,14 @@
|
|||||||
"deleteFailed": "Не удалось удалить робота",
|
"deleteFailed": "Не удалось удалить робота",
|
||||||
"search": "Поиск роботов..."
|
"search": "Поиск роботов..."
|
||||||
},
|
},
|
||||||
|
"mainmenu": {
|
||||||
|
"recordings": "Роботы",
|
||||||
|
"runs": "Запуски",
|
||||||
|
"proxy": "Прокси",
|
||||||
|
"apikey": "API ключ",
|
||||||
|
"feedback": "Присоединиться к Maxun Cloud",
|
||||||
|
"apidocs": "Веб-сайт в API"
|
||||||
|
},
|
||||||
"recordingpage": {
|
"recordingpage": {
|
||||||
"stopRecording": "Остановить запись",
|
"stopRecording": "Остановить запись",
|
||||||
"recording": "Запись...",
|
"recording": "Запись...",
|
||||||
@@ -375,5 +383,86 @@
|
|||||||
"created": "Создано",
|
"created": "Создано",
|
||||||
"sent": "Отправлено",
|
"sent": "Отправлено",
|
||||||
"copied": "Скопировано"
|
"copied": "Скопировано"
|
||||||
|
},
|
||||||
|
"robotCreate": {
|
||||||
|
"title": "Создать нового робота",
|
||||||
|
"tabs": {
|
||||||
|
"extract": "Извлечь",
|
||||||
|
"scrape": "Скрейпинг",
|
||||||
|
"crawl": "Обход",
|
||||||
|
"search": "Поиск"
|
||||||
|
},
|
||||||
|
"chooseMode": "Выберите способ создания",
|
||||||
|
"modes": {
|
||||||
|
"recorder": {
|
||||||
|
"title": "Режим записи",
|
||||||
|
"description": "Запишите свои действия в рабочий процесс"
|
||||||
|
},
|
||||||
|
"ai": {
|
||||||
|
"title": "AI режим",
|
||||||
|
"description": "Опишите задачу. Он создаст её для вас",
|
||||||
|
"label": "Beta"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extract": {
|
||||||
|
"description": "Извлекайте структурированные данные с веб-сайтов используя AI или записывайте свой собственный процесс извлечения",
|
||||||
|
"websiteUrl": "URL веб-сайта",
|
||||||
|
"websiteUrlOptional": "URL веб-сайта (необязательно)",
|
||||||
|
"websiteUrlPlaceholder": "Например: https://www.ycombinator.com/companies/",
|
||||||
|
"startRecording": "Начать запись",
|
||||||
|
"starting": "Запуск...",
|
||||||
|
"name": "Название",
|
||||||
|
"namePlaceholder": "Название",
|
||||||
|
"aiPrompt": "Промпт для извлечения",
|
||||||
|
"aiPromptPlaceholder": "Например: Извлечь первые 15 названий компаний, описания и информацию о партиях",
|
||||||
|
"aiExample": "Например: 'Извлечь названия продуктов, цены и рейтинги'",
|
||||||
|
"llmProvider": "LLM Провайдер",
|
||||||
|
"llmProviderOllama": "Ollama (Локально)",
|
||||||
|
"llmProviderAnthropic": "Anthropic (Claude)",
|
||||||
|
"llmProviderOpenAI": "OpenAI (GPT-4)",
|
||||||
|
"model": "Модель",
|
||||||
|
"modelDefault": "По умолчанию (llama3.2-vision)",
|
||||||
|
"ollamaBaseUrl": "Ollama Base URL (необязательно)",
|
||||||
|
"generate": "Создать робота",
|
||||||
|
"generating": "Создание...",
|
||||||
|
"createAndRun": "Создать и запустить робота",
|
||||||
|
"creatingAndRunning": "Создание и запуск...",
|
||||||
|
"apiKey": "API ключ (необязательно, если установлен в .env)",
|
||||||
|
"apiKeyPlaceholder": "API ключ"
|
||||||
|
},
|
||||||
|
"scrape": {
|
||||||
|
"description": "Скрейпить весь контент страницы в различных форматах",
|
||||||
|
"websiteUrl": "URL веб-сайта",
|
||||||
|
"robotName": "Название робота (необязательно)",
|
||||||
|
"outputFormats": "Форматы вывода",
|
||||||
|
"createRobot": "Создать робота",
|
||||||
|
"creating": "Создание..."
|
||||||
|
},
|
||||||
|
"crawl": {
|
||||||
|
"description": "Обходить веб-сайт и извлекать данные с нескольких страниц",
|
||||||
|
"websiteUrl": "URL веб-сайта",
|
||||||
|
"robotName": "Название робота (необязательно)",
|
||||||
|
"maxPages": "Максимум страниц для обхода",
|
||||||
|
"maxDepth": "Максимальная глубина обхода",
|
||||||
|
"includePaths": "Включить пути (через запятую, необязательно)",
|
||||||
|
"excludePaths": "Исключить пути (через запятую, необязательно)",
|
||||||
|
"createRobot": "Создать робота",
|
||||||
|
"creating": "Создание...",
|
||||||
|
"advancedOptions": "Дополнительные опции"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"description": "Искать информацию в интернете используя AI",
|
||||||
|
"query": "Поисковой запрос",
|
||||||
|
"queryPlaceholder": "О чём вы хотите узнать?",
|
||||||
|
"robotName": "Название робота (необязательно)",
|
||||||
|
"createRobot": "Создать поискового робота",
|
||||||
|
"creating": "Создание..."
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"urlRequired": "URL обязателен",
|
||||||
|
"queryRequired": "Поисковой запрос обязателен",
|
||||||
|
"failedToStart": "Не удалось начать запись. Попробуйте снова",
|
||||||
|
"failedToCreate": "Не удалось создать робота"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -364,6 +364,14 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
>
|
>
|
||||||
Türkçe
|
Türkçe
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
changeLanguage("ru");
|
||||||
|
handleMenuClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Русский
|
||||||
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open('https://docs.maxun.dev/development/i18n', '_blank');
|
window.open('https://docs.maxun.dev/development/i18n', '_blank');
|
||||||
@@ -468,6 +476,14 @@ export const NavBar: React.FC<NavBarProps> = ({
|
|||||||
>
|
>
|
||||||
Türkçe
|
Türkçe
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem
|
||||||
|
onClick={() => {
|
||||||
|
changeLanguage("ru");
|
||||||
|
handleMenuClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Русский
|
||||||
|
</MenuItem>
|
||||||
<MenuItem
|
<MenuItem
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open('https://docs.maxun.dev/development/i18n', '_blank');
|
window.open('https://docs.maxun.dev/development/i18n', '_blank');
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ const RobotCreate: React.FC = () => {
|
|||||||
<ArrowBack />
|
<ArrowBack />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Typography variant="h5" component="h1">
|
<Typography variant="h5" component="h1">
|
||||||
Create New Robot
|
{t('robotCreate.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -299,10 +299,10 @@ const RobotCreate: React.FC = () => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tab label="Extract" id="extract-robot" aria-controls="extract-robot" />
|
<Tab label={t('robotCreate.tabs.extract')} id="extract-robot" aria-controls="extract-robot" />
|
||||||
<Tab label="Scrape" id="scrape-robot" aria-controls="scrape-robot" />
|
<Tab label={t('robotCreate.tabs.scrape')} id="scrape-robot" aria-controls="scrape-robot" />
|
||||||
<Tab label="Crawl" id="crawl-robot" aria-controls="crawl-robot" />
|
<Tab label={t('robotCreate.tabs.crawl')} id="crawl-robot" aria-controls="crawl-robot" />
|
||||||
<Tab label="Search" id="search-robot" aria-controls="search-robot" />
|
<Tab label={t('robotCreate.tabs.search')} id="search-robot" aria-controls="search-robot" />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
@@ -321,11 +321,11 @@ const RobotCreate: React.FC = () => {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Typography variant="body2" color="text.secondary" mb={3}>
|
<Typography variant="body2" color="text.secondary" mb={3}>
|
||||||
Extract structured data from websites using AI or record your own extraction workflow.
|
{t('robotCreate.extract.description')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box sx={{ width: '100%', maxWidth: 700, mb: 3 }}>
|
<Box sx={{ width: '100%', maxWidth: 700, mb: 3 }}>
|
||||||
<Typography variant="subtitle1" gutterBottom sx={{ mb: 2 }} color="text.secondary">
|
<Typography variant="subtitle1" gutterBottom sx={{ mb: 2 }} color="text.secondary">
|
||||||
Choose How to Build
|
{t('robotCreate.chooseMode')}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', gap: 2 }}>
|
<Box sx={{ display: 'flex', gap: 2 }}>
|
||||||
@@ -345,10 +345,10 @@ const RobotCreate: React.FC = () => {
|
|||||||
<CardContent sx={{ textAlign: 'center', py: 3, color:"text.secondary" }}>
|
<CardContent sx={{ textAlign: 'center', py: 3, color:"text.secondary" }}>
|
||||||
<HighlightAlt sx={{ fontSize: 32, mb: 1 }} />
|
<HighlightAlt sx={{ fontSize: 32, mb: 1 }} />
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
Recorder Mode
|
{t('robotCreate.modes.recorder.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
Record your actions into a workflow.
|
{t('robotCreate.modes.recorder.description')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -380,16 +380,16 @@ const RobotCreate: React.FC = () => {
|
|||||||
fontSize: '0.7rem',
|
fontSize: '0.7rem',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Beta
|
{t('robotCreate.modes.ai.label')}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<CardContent sx={{ textAlign: 'center', py: 3, color:"text.secondary" }}>
|
<CardContent sx={{ textAlign: 'center', py: 3, color:"text.secondary" }}>
|
||||||
<AutoAwesome sx={{ fontSize: 32, mb: 1 }} />
|
<AutoAwesome sx={{ fontSize: 32, mb: 1 }} />
|
||||||
<Typography variant="h6" gutterBottom>
|
<Typography variant="h6" gutterBottom>
|
||||||
AI Mode
|
{t('robotCreate.modes.ai.title')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
Describe the task. It builds it for you.
|
{t('robotCreate.modes.ai.description')}
|
||||||
</Typography>
|
</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -399,45 +399,45 @@ const RobotCreate: React.FC = () => {
|
|||||||
<Box sx={{ width: '100%', maxWidth: 700 }}>
|
<Box sx={{ width: '100%', maxWidth: 700 }}>
|
||||||
<Box sx={{ mb: 3 }}>
|
<Box sx={{ mb: 3 }}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Name"
|
placeholder={t('robotCreate.extract.namePlaceholder')}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={extractRobotName}
|
value={extractRobotName}
|
||||||
onChange={(e) => setExtractRobotName(e.target.value)}
|
onChange={(e) => setExtractRobotName(e.target.value)}
|
||||||
label="Name"
|
label={t('robotCreate.extract.name')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ mb: 3 }}>
|
<Box sx={{ mb: 3 }}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Example: Extract first 15 company names, descriptions, and batch information"
|
placeholder={t('robotCreate.extract.aiPromptPlaceholder')}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
multiline
|
multiline
|
||||||
rows={3}
|
rows={3}
|
||||||
value={aiPrompt}
|
value={aiPrompt}
|
||||||
onChange={(e) => setAiPrompt(e.target.value)}
|
onChange={(e) => setAiPrompt(e.target.value)}
|
||||||
label="Extraction Prompt"
|
label={t('robotCreate.extract.aiPrompt')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ mb: 3 }}>
|
<Box sx={{ mb: 3 }}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Example: https://www.ycombinator.com/companies/"
|
placeholder={t('robotCreate.extract.websiteUrlPlaceholder')}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={url}
|
value={url}
|
||||||
onChange={(e) => setUrl(e.target.value)}
|
onChange={(e) => setUrl(e.target.value)}
|
||||||
label="Website URL (Optional)"
|
label={t('robotCreate.extract.websiteUrlOptional')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', gap: 2, mb: 3 }}>
|
<Box sx={{ display: 'flex', gap: 2, mb: 3 }}>
|
||||||
<FormControl sx={{ flex: 1 }}>
|
<FormControl sx={{ flex: 1 }}>
|
||||||
<InputLabel>LLM Provider</InputLabel>
|
<InputLabel>{t('robotCreate.extract.llmProvider')}</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
value={llmProvider}
|
value={llmProvider}
|
||||||
label="LLM Provider"
|
label={t('robotCreate.extract.llmProvider')}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const provider = e.target.value as 'anthropic' | 'openai' | 'ollama';
|
const provider = e.target.value as 'anthropic' | 'openai' | 'ollama';
|
||||||
setLlmProvider(provider);
|
setLlmProvider(provider);
|
||||||
@@ -449,22 +449,22 @@ const RobotCreate: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuItem value="ollama">Ollama (Local)</MenuItem>
|
<MenuItem value="ollama">{t('robotCreate.extract.llmProviderOllama')}</MenuItem>
|
||||||
<MenuItem value="anthropic">Anthropic (Claude)</MenuItem>
|
<MenuItem value="anthropic">{t('robotCreate.extract.llmProviderAnthropic')}</MenuItem>
|
||||||
<MenuItem value="openai">OpenAI (GPT-4)</MenuItem>
|
<MenuItem value="openai">{t('robotCreate.extract.llmProviderOpenAI')}</MenuItem>
|
||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
<FormControl sx={{ flex: 1 }}>
|
<FormControl sx={{ flex: 1 }}>
|
||||||
<InputLabel>Model</InputLabel>
|
<InputLabel>{t('robotCreate.extract.model')}</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
value={llmModel}
|
value={llmModel}
|
||||||
label="Model"
|
label={t('robotCreate.extract.model')}
|
||||||
onChange={(e) => setLlmModel(e.target.value)}
|
onChange={(e) => setLlmModel(e.target.value)}
|
||||||
>
|
>
|
||||||
{llmProvider === 'ollama' ? (
|
{llmProvider === 'ollama' ? (
|
||||||
[
|
[
|
||||||
<MenuItem key="default" value="default">Default (llama3.2-vision)</MenuItem>,
|
<MenuItem key="default" value="default">{t('robotCreate.extract.modelDefault')}</MenuItem>,
|
||||||
<MenuItem key="llama3.2-vision" value="llama3.2-vision">llama3.2-vision</MenuItem>,
|
<MenuItem key="llama3.2-vision" value="llama3.2-vision">llama3.2-vision</MenuItem>,
|
||||||
<MenuItem key="llama3.2" value="llama3.2">llama3.2</MenuItem>
|
<MenuItem key="llama3.2" value="llama3.2">llama3.2</MenuItem>
|
||||||
]
|
]
|
||||||
@@ -495,7 +495,7 @@ const RobotCreate: React.FC = () => {
|
|||||||
type="password"
|
type="password"
|
||||||
value={llmApiKey}
|
value={llmApiKey}
|
||||||
onChange={(e) => setLlmApiKey(e.target.value)}
|
onChange={(e) => setLlmApiKey(e.target.value)}
|
||||||
label="API Key (Optional if set in .env)"
|
label={t('robotCreate.extract.apiKey')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
@@ -508,7 +508,7 @@ const RobotCreate: React.FC = () => {
|
|||||||
fullWidth
|
fullWidth
|
||||||
value={llmBaseUrl}
|
value={llmBaseUrl}
|
||||||
onChange={(e) => setLlmBaseUrl(e.target.value)}
|
onChange={(e) => setLlmBaseUrl(e.target.value)}
|
||||||
label="Ollama Base URL (Optional)"
|
label={t('robotCreate.extract.ollamaBaseUrl')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
@@ -626,7 +626,7 @@ const RobotCreate: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : null}
|
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : null}
|
||||||
>
|
>
|
||||||
{isLoading ? 'Creating & Running...' : 'Create & Run Robot'}
|
{isLoading ? t('robotCreate.extract.creatingAndRunning') : t('robotCreate.extract.createAndRun')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
@@ -635,12 +635,12 @@ const RobotCreate: React.FC = () => {
|
|||||||
<>
|
<>
|
||||||
<Box sx={{ width: '100%', maxWidth: 700, mb: 3 }}>
|
<Box sx={{ width: '100%', maxWidth: 700, mb: 3 }}>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder="Example: https://www.ycombinator.com/companies/"
|
placeholder={t('robotCreate.extract.websiteUrlPlaceholder')}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
fullWidth
|
fullWidth
|
||||||
value={url}
|
value={url}
|
||||||
onChange={(e) => setUrl(e.target.value)}
|
onChange={(e) => setUrl(e.target.value)}
|
||||||
label="Website URL"
|
label={t('robotCreate.extract.websiteUrl')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ width: '100%', maxWidth: 700 }}>
|
<Box sx={{ width: '100%', maxWidth: 700 }}>
|
||||||
@@ -658,7 +658,7 @@ const RobotCreate: React.FC = () => {
|
|||||||
}}
|
}}
|
||||||
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : null}
|
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : null}
|
||||||
>
|
>
|
||||||
{isLoading ? 'Starting...' : 'Start Recording'}
|
{isLoading ? t('robotCreate.extract.starting') : t('robotCreate.extract.startRecording')}
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ i18n
|
|||||||
.init({
|
.init({
|
||||||
fallbackLng: 'en',
|
fallbackLng: 'en',
|
||||||
debug: import.meta.env.DEV,
|
debug: import.meta.env.DEV,
|
||||||
supportedLngs: ['en', 'es', 'ja', 'zh','de', 'tr'],
|
supportedLngs: ['en', 'es', 'ja', 'zh','de', 'tr', 'ru'],
|
||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false, // React already escapes
|
escapeValue: false, // React already escapes
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,9 +11,14 @@ export default defineConfig(() => {
|
|||||||
'import.meta.env.VITE_BACKEND_URL': JSON.stringify(process.env.VITE_BACKEND_URL),
|
'import.meta.env.VITE_BACKEND_URL': JSON.stringify(process.env.VITE_BACKEND_URL),
|
||||||
'import.meta.env.VITE_PUBLIC_URL': JSON.stringify(publicUrl),
|
'import.meta.env.VITE_PUBLIC_URL': JSON.stringify(publicUrl),
|
||||||
},
|
},
|
||||||
|
css: {
|
||||||
|
postcss: {
|
||||||
|
plugins: [], // Empty plugins array - NO PostCSS processing
|
||||||
|
},
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
host: new URL(publicUrl).hostname,
|
host: '0.0.0.0', // Listen on all interfaces for Docker
|
||||||
port: parseInt(new URL(publicUrl).port),
|
port: 5174,
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: 'build',
|
outDir: 'build',
|
||||||
|
|||||||
Reference in New Issue
Block a user