From 5684243215afcec2cf453568dad418455aea76d8 Mon Sep 17 00:00:00 2001 From: AmitChauhan63390 Date: Sat, 7 Dec 2024 22:20:17 +0530 Subject: [PATCH 001/238] langs --- package.json | 6 +- public/locales/ar.json | 0 public/locales/en.json | 13 + public/locales/es.json | 13 + public/locales/ja.json | 13 + public/locales/zh.json | 13 + src/App.tsx | 29 ++- src/components/molecules/NavBar.tsx | 370 +++++++++++++++++++++------- src/i18n.ts | 22 ++ src/index.tsx | 1 + src/pages/Login.tsx | 256 ++++++++++--------- 11 files changed, 508 insertions(+), 228 deletions(-) create mode 100644 public/locales/ar.json create mode 100644 public/locales/en.json create mode 100644 public/locales/es.json create mode 100644 public/locales/ja.json create mode 100644 public/locales/zh.json create mode 100644 src/i18n.ts diff --git a/package.json b/package.json index b6b735373..8b9d5d66b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,9 @@ "fortawesome": "^0.0.1-security", "google-auth-library": "^9.14.1", "googleapis": "^144.0.0", + "i18next": "^24.0.2", + "i18next-browser-languagedetector": "^8.0.0", + "i18next-http-backend": "^3.0.1", "ioredis": "^5.4.1", "joi": "^17.6.0", "jsonwebtoken": "^9.0.2", @@ -56,6 +59,7 @@ "react": "^18.0.0", "react-dom": "^18.0.0", "react-highlight": "0.15.0", + "react-i18next": "^15.1.3", "react-router-dom": "^6.26.1", "react-simple-code-editor": "^0.11.2", "react-transition-group": "^4.4.2", @@ -110,4 +114,4 @@ "ts-node": "^10.4.0", "vite": "^5.4.10" } -} \ No newline at end of file +} diff --git a/public/locales/ar.json b/public/locales/ar.json new file mode 100644 index 000000000..e69de29bb diff --git a/public/locales/en.json b/public/locales/en.json new file mode 100644 index 000000000..232813006 --- /dev/null +++ b/public/locales/en.json @@ -0,0 +1,13 @@ +{ + "login": { + "title": "Welcome Back!", + "email": "Email", + "password": "Password", + "button": "Login", + "loading": "Loading", + "register_prompt": "Don't have an account?", + "register_link": "Register", + "welcome_notification": "Welcome to Maxun!", + "error_notification": "Login Failed. Please try again." + } + } \ No newline at end of file diff --git a/public/locales/es.json b/public/locales/es.json new file mode 100644 index 000000000..00589622e --- /dev/null +++ b/public/locales/es.json @@ -0,0 +1,13 @@ +{ + "app": { + "name": "Maxun", + "version": "beta" + }, + "login": { + "title": "¡Bienvenido de nuevo!", + "email": "Correo electrónico", + "password": "Contraseña", + "button": "Iniciar sesión", + "register_prompt": "¿No tienes una cuenta? Regístrate" + } + } \ No newline at end of file diff --git a/public/locales/ja.json b/public/locales/ja.json new file mode 100644 index 000000000..80a594eb3 --- /dev/null +++ b/public/locales/ja.json @@ -0,0 +1,13 @@ +{ + "app": { + "name": "Maxun", + "version": "beta" + }, + "login": { + "title": "おかえりなさい!", + "email": "メールアドレス", + "password": "パスワード", + "button": "ログイン", + "register_prompt": "アカウントをお持ちでない方は、新規登録" + } + } \ No newline at end of file diff --git a/public/locales/zh.json b/public/locales/zh.json new file mode 100644 index 000000000..7fa8bb608 --- /dev/null +++ b/public/locales/zh.json @@ -0,0 +1,13 @@ +{ + "app": { + "name": "Maxun", + "version": "beta" + }, + "login": { + "title": "欢迎回来!", + "email": "电子邮件", + "password": "密码", + "button": "登录", + "register_prompt": "没有账号?注册" + } + } \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index c37de9ea4..02dff1347 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,10 @@ -import React from 'react'; -import { Routes, Route } from 'react-router-dom'; +import React from "react"; +import { Routes, Route } from "react-router-dom"; import { ThemeProvider, createTheme } from "@mui/material/styles"; import { GlobalInfoProvider } from "./context/globalInfo"; import { PageWrapper } from "./pages/PageWrappper"; +import i18n from "./i18n"; + const theme = createTheme({ palette: { @@ -20,14 +22,14 @@ const theme = createTheme({ }, containedPrimary: { // Styles for 'contained' variant with 'primary' color - '&:hover': { + "&:hover": { backgroundColor: "#ff66d9", }, }, outlined: { // Apply white background for all 'outlined' variant buttons backgroundColor: "#ffffff", - '&:hover': { + "&:hover": { backgroundColor: "#f0f0f0", // Optional lighter background on hover }, }, @@ -36,7 +38,7 @@ const theme = createTheme({ MuiLink: { styleOverrides: { root: { - '&:hover': { + "&:hover": { color: "#ff00c3", }, }, @@ -63,7 +65,7 @@ const theme = createTheme({ standardInfo: { backgroundColor: "#fce1f4", color: "#ff00c3", - '& .MuiAlert-icon': { + "& .MuiAlert-icon": { color: "#ff00c3", }, }, @@ -72,7 +74,7 @@ const theme = createTheme({ MuiAlertTitle: { styleOverrides: { root: { - '& .MuiAlert-icon': { + "& .MuiAlert-icon": { color: "#ffffff", }, }, @@ -81,15 +83,16 @@ const theme = createTheme({ }, }); - function App() { return ( - - - } /> - - + + + + } /> + + + ); } diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 4c0b7296a..b068aa3ab 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -1,134 +1,322 @@ -import React, { useState, useContext } from 'react'; -import axios from 'axios'; +import React, { useState, useContext } from "react"; +import axios from "axios"; import styled from "styled-components"; import { stopRecording } from "../../api/recording"; import { useGlobalInfoStore } from "../../context/globalInfo"; -import { IconButton, Menu, MenuItem, Typography, Avatar, Chip, } from "@mui/material"; +import { IconButton, Menu, MenuItem, Typography, Chip } from "@mui/material"; import { AccountCircle, Logout, Clear } from "@mui/icons-material"; -import { useNavigate } from 'react-router-dom'; -import { AuthContext } from '../../context/auth'; -import { SaveRecording } from '../molecules/SaveRecording'; -import DiscordIcon from '../atoms/DiscordIcon'; -import { apiUrl } from '../../apiConfig'; +import { useNavigate } from "react-router-dom"; +import { AuthContext } from "../../context/auth"; +import { SaveRecording } from "../molecules/SaveRecording"; +import DiscordIcon from "../atoms/DiscordIcon"; +import { apiUrl } from "../../apiConfig"; import MaxunLogo from "../../assets/maxunlogo.png"; +import { useTranslation } from "react-i18next"; // Import useTranslation hook interface NavBarProps { recordingName: string; isRecording: boolean; } -export const NavBar: React.FC = ({ recordingName, isRecording }) => { - const { notify, browserId, setBrowserId, recordingUrl } = useGlobalInfoStore(); +export const NavBar: React.FC = ({ + recordingName, + isRecording, +}) => { + const { notify, browserId, setBrowserId } = useGlobalInfoStore(); const { state, dispatch } = useContext(AuthContext); const { user } = state; const navigate = useNavigate(); + const { t, i18n } = useTranslation(); // Get translation function and i18n methods const [anchorEl, setAnchorEl] = useState(null); + const [langAnchorEl, setLangAnchorEl] = useState(null); const handleMenuOpen = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; + const handleLangMenuOpen = (event: React.MouseEvent) => { + setLangAnchorEl(event.currentTarget); + }; + const handleMenuClose = () => { setAnchorEl(null); + setLangAnchorEl(null); }; const logout = async () => { - dispatch({ type: 'LOGOUT' }); - window.localStorage.removeItem('user'); + dispatch({ type: "LOGOUT" }); + window.localStorage.removeItem("user"); const { data } = await axios.get(`${apiUrl}/auth/logout`); - notify('success', data.message); - navigate('/login'); + notify("success", data.message); + navigate("/login"); }; const goToMainMenu = async () => { if (browserId) { await stopRecording(browserId); - notify('warning', 'Current Recording was terminated'); + notify("warning", "Current Recording was terminated"); setBrowserId(null); } - navigate('/'); + navigate("/"); + }; + + const changeLanguage = (lang: string) => { + i18n.changeLanguage(lang); // Change language dynamically + localStorage.setItem("language", lang); // Persist language to localStorage }; return ( -
- -
Maxun
- +
+ +
+ Maxun +
+
- { - user ? ( -
- {!isRecording ? ( - <> - + {!isRecording ? ( + <> + + + + + + + {user.email} + + + { + handleMenuClose(); + logout(); }} > - - - - - - {user.email} - - - { handleMenuClose(); logout(); }}> - Logout - - - - ) : ( - <> - - - Discard - - - - )} -
- ) : "" - } + {t("logout")} + + + {/* Language dropdown */} + + ) : ( + <> + + + {t("discard")} + + + + )} + + {t("language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("ar"); + handleMenuClose(); + }} + > + العربية + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + +
+ ) : ( + <> + {t("language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("ar"); + handleMenuClose(); + }} + > + العربية + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + + )} + +
); }; @@ -136,7 +324,7 @@ export const NavBar: React.FC = ({ recordingName, isRecording }) => const NavBarWrapper = styled.div` grid-area: navbar; background-color: white; - padding:5px; + padding: 5px; display: flex; justify-content: space-between; border-bottom: 1px solid #e0e0e0; diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 000000000..f318cd5cd --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,22 @@ +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import Backend from 'i18next-http-backend'; +import LanguageDetector from 'i18next-browser-languagedetector'; + +i18n + .use(Backend) + .use(LanguageDetector) + .use(initReactI18next) + .init({ + fallbackLng: 'en', + debug: import.meta.env.DEV, + supportedLngs: ['en', 'es', 'ja', 'zh', 'ar'], + interpolation: { + escapeValue: false, // React already escapes + }, + backend: { + loadPath: '/locales/{{lng}}.json', + }, + }); + +export default i18n; \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index 8c14f60ac..96f914ff7 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,6 +3,7 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import { BrowserRouter } from 'react-router-dom'; import App from './App'; +import i18n from "./i18n" const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 87f90b531..3d70bfc2f 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,134 +1,144 @@ -import axios from "axios"; -import { useState, useContext, useEffect, FormEvent } from "react"; -import { useNavigate, Link } from "react-router-dom"; -import { AuthContext } from "../context/auth"; -import { Box, Typography, TextField, Button, CircularProgress, Grid } from "@mui/material"; -import { useGlobalInfoStore } from "../context/globalInfo"; +import axios from "axios"; +import { useState, useContext, useEffect, FormEvent } from "react"; +import { useNavigate, Link } from "react-router-dom"; +import { AuthContext } from "../context/auth"; +import { Box, Typography, TextField, Button, CircularProgress, Grid } from "@mui/material"; +import { useGlobalInfoStore } from "../context/globalInfo"; import { apiUrl } from "../apiConfig"; +import { useTranslation } from 'react-i18next'; +import i18n from '../i18n'; // Add this import const Login = () => { - const [form, setForm] = useState({ - email: "", - password: "", - }); - const [loading, setLoading] = useState(false); - const { notify } = useGlobalInfoStore(); - const { email, password } = form; + const { t } = useTranslation(); + console.log(i18n) // Add translation hook + console.log(t) + const [form, setForm] = useState({ + email: "", + password: "", + }); + const [loading, setLoading] = useState(false); + const { notify } = useGlobalInfoStore(); + const { email, password } = form; - const { state, dispatch } = useContext(AuthContext); - const { user } = state; + const { state, dispatch } = useContext(AuthContext); + const { user } = state; - const navigate = useNavigate(); + const navigate = useNavigate(); - useEffect(() => { - if (user) { - navigate("/"); - } - }, [user, navigate]); + useEffect(() => { + if (user) { + navigate("/"); + } + }, [user, navigate]); - const handleChange = (e: any) => { - const { name, value } = e.target; - setForm({ ...form, [name]: value }); - }; + const handleChange = (e: any) => { + const { name, value } = e.target; + setForm({ ...form, [name]: value }); + }; - const submitForm = async (e: any) => { - e.preventDefault(); - setLoading(true); - try { - const { data } = await axios.post(`${apiUrl}/auth/login`, { - email, - password, - }); - dispatch({ type: "LOGIN", payload: data }); - notify("success", "Welcome to Maxun!"); - window.localStorage.setItem("user", JSON.stringify(data)); - navigate("/"); - } catch (err) { - notify("error", "Login Failed. Please try again."); - setLoading(false); - } - }; + const submitForm = async (e: any) => { + e.preventDefault(); + setLoading(true); + try { + const { data } = await axios.post(`${apiUrl}/auth/login`, { + email, + password, + }); + dispatch({ type: "LOGIN", payload: data }); + notify("success", t('login.welcome_notification')); // Translated notification + window.localStorage.setItem("user", JSON.stringify(data)); + navigate("/"); + } catch (err) { + notify("error", t('login.error_notification')); // Translated error + setLoading(false); + } + }; - return ( - - - - logo - - Welcome Back! - - - - - - Don’t have an account?{" "} - - Register - - - - - - ); + // Language switcher function + const changeLanguage = (lng: string) => { + i18n.changeLanguage(lng); + }; + + return ( + + {/* Language Switcher Buttons */} + + + logo + + {t('login.title')} + + + + + + {t('login.register_prompt')}{" "} + + {t('login.register_link')} + + + + + ); }; -export default Login; +export default Login; \ No newline at end of file From 077234212af3e920e78699d25a1acedc789da28b Mon Sep 17 00:00:00 2001 From: AmitChauhan63390 Date: Tue, 10 Dec 2024 20:40:59 +0530 Subject: [PATCH 002/238] language support --- public/locales/ar.json | 0 public/locales/de.json | 50 +++++++++++++ public/locales/en.json | 40 +++++++++++ public/locales/ja.json | 55 +++++++++++--- src/components/molecules/NavBar.tsx | 9 +++ src/components/molecules/RecordingsTable.tsx | 76 +++++++++++--------- src/components/organisms/MainMenu.tsx | 16 +++-- src/i18n.ts | 2 +- src/pages/Login.tsx | 8 +-- src/pages/Register.tsx | 20 ++++-- 10 files changed, 215 insertions(+), 61 deletions(-) delete mode 100644 public/locales/ar.json create mode 100644 public/locales/de.json diff --git a/public/locales/ar.json b/public/locales/ar.json deleted file mode 100644 index e69de29bb..000000000 diff --git a/public/locales/de.json b/public/locales/de.json new file mode 100644 index 000000000..d12b2489a --- /dev/null +++ b/public/locales/de.json @@ -0,0 +1,50 @@ +{ + "login": { + "title": "Willkommen zurück!", + "email": "E-Mail", + "password": "Passwort", + "button": "Einloggen", + "loading": "Lädt", + "register_prompt": "Noch keinen Account?", + "register_link": "Registrieren", + "welcome_notification": "Willkommen bei Maxun!", + "error_notification": "Anmeldung fehlgeschlagen. Bitte versuchen Sie es erneut." + }, + "register": { + "title": "Konto registrieren", + "email": "E-Mail", + "password": "Passwort", + "button": "Registrieren", + "loading": "Lädt", + "register_prompt": "Bereits ein Konto?", + "login_link": "Einloggen", + "welcome_notification": "Willkommen bei Maxun!", + "error_notification": "Registrierung fehlgeschlagen. Bitte versuchen Sie es erneut." + }, + "recordingtable": { + "run": "Ausführen", + "name": "Name", + "schedule": "Zeitplan", + "integrate": "Integrieren", + "settings": "Einstellungen", + "options": "Optionen", + "heading": "Meine Roboter", + "new": "Roboter erstellen", + "modal": { + "title": "Geben Sie die URL ein", + "label": "URL", + "button": "Aufnahme starten" + }, + "edit": "Bearbeiten", + "delete": "Löschen", + "duplicate": "Duplizieren" + }, + "mainmenu": { + "recordings": "Roboter", + "runs": "Ausführungen", + "proxy": "Proxy", + "apikey": "API-Schlüssel", + "feedback": "Maxun Cloud beitreten", + "apidocs": "API-Dokumentation" + } +} diff --git a/public/locales/en.json b/public/locales/en.json index 232813006..897e17296 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -9,5 +9,45 @@ "register_link": "Register", "welcome_notification": "Welcome to Maxun!", "error_notification": "Login Failed. Please try again." + }, + "register": { + "title": "Register Account", + "email": "Email", + "password": "Password", + "button": "Register", + "loading": "Loading", + "register_prompt": "Already have an account?", + "login_link": "Login", + "welcome_notification": "Welcome to Maxun!", + "error_notification": "Registeration Failed. Please try again." + }, + "recordingtable":{ + "run": "Run", + "name": "Name", + "schedule": "Schedule", + "integrate": "Integrate", + "settings": "Settings", + "options": "Options", + "heading":"My Robots", + "new":"Create Robot", + "modal":{ + "title":"Enter the URL", + "label":"URL", + "button":"Start Recording" + }, + "edit":"Edit", + "delete":"Delete", + "duplicate":"Duplicate", + "search":"Search Robots..." + + }, + "mainmenu":{ + "recordings": "Robots", + "runs": "Runs", + "proxy": "Proxy", + "apikey": "API Key", + "feedback":"Join Maxun Cloud", + "apidocs":"API Docs" + } } \ No newline at end of file diff --git a/public/locales/ja.json b/public/locales/ja.json index 80a594eb3..88686e62b 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -1,13 +1,50 @@ { - "app": { - "name": "Maxun", - "version": "beta" - }, - "login": { - "title": "おかえりなさい!", + "login": { + "title": "お帰りなさい!", "email": "メールアドレス", "password": "パスワード", "button": "ログイン", - "register_prompt": "アカウントをお持ちでない方は、新規登録" - } - } \ No newline at end of file + "loading": "読み込み中", + "register_prompt": "アカウントをお持ちでないですか?", + "register_link": "登録する", + "welcome_notification": "Maxunへようこそ!", + "error_notification": "ログインに失敗しました。もう一度お試しください。" + }, + "register": { + "title": "アカウントを登録する", + "email": "メールアドレス", + "password": "パスワード", + "button": "登録する", + "loading": "読み込み中", + "register_prompt": "既にアカウントをお持ちですか?", + "login_link": "ログイン", + "welcome_notification": "Maxunへようこそ!", + "error_notification": "登録に失敗しました。もう一度お試しください。" + }, + "recordingtable": { + "run": "実行", + "name": "名前", + "schedule": "スケジュール", + "integrate": "統合", + "settings": "設定", + "options": "オプション", + "heading": "私のロボット", + "new": "ロボットを作成", + "modal": { + "title": "URLを入力してください", + "label": "URL", + "button": "録画を開始" + }, + "edit": "編集", + "delete": "削除", + "duplicate": "複製" + }, + "mainmenu": { + "recordings": "ロボット", + "runs": "実行", + "proxy": "プロキシ", + "apikey": "APIキー", + "feedback": "Maxunクラウドに参加する", + "apidocs": "APIドキュメント" + } +} diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index b068aa3ab..958492e6d 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -245,6 +245,15 @@ export const NavBar: React.FC = ({ > 中文 + { + changeLanguage("de"); + handleMenuClose(); + }} + > + German + + ) : ( diff --git a/src/components/molecules/RecordingsTable.tsx b/src/components/molecules/RecordingsTable.tsx index e9f0aebc2..e298445fd 100644 --- a/src/components/molecules/RecordingsTable.tsx +++ b/src/components/molecules/RecordingsTable.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { useTranslation } from 'react-i18next'; import Paper from '@mui/material/Paper'; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; @@ -19,6 +20,7 @@ import { useNavigate } from 'react-router-dom'; import { stopRecording } from "../../api/recording"; import { GenericModal } from '../atoms/GenericModal'; + /** TODO: * 1. allow editing existing robot after persisting browser steps */ @@ -31,30 +33,9 @@ interface Column { format?: (value: string) => string; } -const columns: readonly Column[] = [ - { id: 'interpret', label: 'Run', minWidth: 80 }, - { id: 'name', label: 'Name', minWidth: 80 }, - { - id: 'schedule', - label: 'Schedule', - minWidth: 80, - }, - { - id: 'integrate', - label: 'Integrate', - minWidth: 80, - }, - { - id: 'settings', - label: 'Settings', - minWidth: 80, - }, - { - id: 'options', - label: 'Options', - minWidth: 80, - }, -]; + + + interface Data { id: string; @@ -76,12 +57,38 @@ interface RecordingsTableProps { } export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording, handleEditRobot, handleDuplicateRobot }: RecordingsTableProps) => { + const {t} = useTranslation(); const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(10); const [rows, setRows] = React.useState([]); const [isModalOpen, setModalOpen] = React.useState(false); const [searchTerm, setSearchTerm] = React.useState(''); + const columns: readonly Column[] = [ + { id: 'interpret', label: t('recordingtable.run'), minWidth: 80 }, + { id: 'name', label: t('recordingtable.name'), minWidth: 80 }, + { + id: 'schedule', + label: t('recordingtable.schedule'), + minWidth: 80, + }, + { + id: 'integrate', + label: t('recordingtable.integrate'), + minWidth: 80, + }, + { + id: 'settings', + label: t('recordingtable.settings'), + minWidth: 80, + }, + { + id: 'options', + label: t('recordingtable.options'), + minWidth: 80, + }, + ]; + const { notify, setRecordings, browserId, setBrowserId, recordingUrl, setRecordingUrl, recordingName, setRecordingName, recordingId, setRecordingId } = useGlobalInfoStore(); const navigate = useNavigate(); @@ -154,16 +161,17 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl + return ( - My Robots + {t('recordingtable.heading')} - Create Robot + {t('recordingtable.new')} @@ -300,9 +308,9 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl /> setModalOpen(false)} modalStyle={modalStyle}>
- Enter URL To Extract Data + {t('recordingtable.modal.title')} - Start Training Robot + {t('recordingtable.modal.button')}
@@ -400,6 +408,8 @@ const OptionsButton = ({ handleEdit, handleDelete, handleDuplicate }: OptionsBut setAnchorEl(null); }; + const {t} = useTranslation(); + return ( <> - Edit + {t('recordingtable.edit')} { handleDelete(); handleClose(); }}> - Delete + {t('recordingtable.delete')} { handleDuplicate(); handleClose(); }}> - Duplicate + {t('recordingtable.duplicate')} diff --git a/src/components/organisms/MainMenu.tsx b/src/components/organisms/MainMenu.tsx index dadb6731c..4143ae9f3 100644 --- a/src/components/organisms/MainMenu.tsx +++ b/src/components/organisms/MainMenu.tsx @@ -5,6 +5,9 @@ import Box from '@mui/material/Box'; import { Paper, Button } from "@mui/material"; import { AutoAwesome, FormatListBulleted, VpnKey, Usb, CloudQueue, Code } from "@mui/icons-material"; import { apiUrl } from "../../apiConfig"; +import { useTranslation } from 'react-i18next'; +import i18n from '../../i18n'; + interface MainMenuProps { value: string; @@ -12,6 +15,7 @@ interface MainMenuProps { } export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenuProps) => { + const {t} = useTranslation(); const handleChange = (event: React.SyntheticEvent, newValue: string) => { handleChangeContent(newValue); @@ -47,7 +51,7 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu fontSize: 'medium', }} value="recordings" - label="Robots" + label={t('mainmenu.recordings')} icon={} iconPosition="start" /> @@ -58,7 +62,7 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu fontSize: 'medium', }} value="runs" - label="Runs" + label={t('mainmenu.runs')} icon={} iconPosition="start" /> @@ -69,7 +73,7 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu fontSize: 'medium', }} value="proxy" - label="Proxy" + label={t('mainmenu.proxy')} icon={} iconPosition="start" /> @@ -80,7 +84,7 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu fontSize: 'medium', }} value="apikey" - label="API Key" + label={t('mainmenu.apikey')} icon={} iconPosition="start" /> @@ -88,10 +92,10 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu
diff --git a/src/i18n.ts b/src/i18n.ts index f318cd5cd..c5e84364e 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -10,7 +10,7 @@ i18n .init({ fallbackLng: 'en', debug: import.meta.env.DEV, - supportedLngs: ['en', 'es', 'ja', 'zh', 'ar'], + supportedLngs: ['en', 'es', 'ja', 'zh','de'], interpolation: { escapeValue: false, // React already escapes }, diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 3d70bfc2f..3c8e08c46 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -6,11 +6,11 @@ import { Box, Typography, TextField, Button, CircularProgress, Grid } from "@mui import { useGlobalInfoStore } from "../context/globalInfo"; import { apiUrl } from "../apiConfig"; import { useTranslation } from 'react-i18next'; -import i18n from '../i18n'; // Add this import +import i18n from '../i18n'; const Login = () => { const { t } = useTranslation(); - console.log(i18n) // Add translation hook + console.log(i18n) console.log(t) const [form, setForm] = useState({ email: "", @@ -55,9 +55,7 @@ const Login = () => { }; // Language switcher function - const changeLanguage = (lng: string) => { - i18n.changeLanguage(lng); - }; + return ( { + const {t} = useTranslation(); const [form, setForm] = useState({ email: "", password: "", @@ -40,11 +45,11 @@ const Register = () => { password, }); dispatch({ type: "LOGIN", payload: data }); - notify("success", "Registration Successful!"); + notify("success", t('register.welcome_notification')); window.localStorage.setItem("user", JSON.stringify(data)); navigate("/"); } catch (error:any) { - notify("error", error.response.data || "Registration Failed. Please try again."); + notify("error", error.response.data || t('register.error_notification')); setLoading(false); } }; @@ -82,7 +87,7 @@ const Register = () => { { /> { Loading ) : ( - "Register" + t('register.button') )} - Already have an account?{" "} + {t('register.register_prompt')}{" "} - Login + + {t('register.login_link')} From 5663abe63eaec093a22299a87b007c206617d4aa Mon Sep 17 00:00:00 2001 From: AmitChauhan63390 Date: Tue, 10 Dec 2024 21:45:09 +0530 Subject: [PATCH 003/238] little progress and icon changed --- public/locales/en.json | 13 +++++ public/locales/ja.json | 13 ++++- src/components/molecules/NavBar.tsx | 8 ++- src/components/molecules/RunsTable.tsx | 76 ++++++++++++++------------ src/pages/Register.tsx | 2 +- 5 files changed, 72 insertions(+), 40 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index 897e17296..b6396893b 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -49,5 +49,18 @@ "feedback":"Join Maxun Cloud", "apidocs":"API Docs" + }, + "runstable":{ + "runs":"All Runs", + "runStatus":"Status", + "runName":"Name", + "startedAt":"Started At", + "finishedAt":"Finished At", + "delete":"Delete", + "settings":"Settings", + "search":"Search Runs..." + + + } } \ No newline at end of file diff --git a/public/locales/ja.json b/public/locales/ja.json index 88686e62b..881fd1318 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -37,7 +37,8 @@ }, "edit": "編集", "delete": "削除", - "duplicate": "複製" + "duplicate": "複製", + "search": "ロボットを検索..." }, "mainmenu": { "recordings": "ロボット", @@ -46,5 +47,15 @@ "apikey": "APIキー", "feedback": "Maxunクラウドに参加する", "apidocs": "APIドキュメント" + }, + "runstable": { + "runs": "すべての実行", + "runStatus": "ステータス", + "runName": "名前", + "startedAt": "開始日時", + "finishedAt": "終了日時", + "delete": "削除", + "settings": "設定", + "search": "実行を検索..." } } diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 958492e6d..ba607fe46 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -4,7 +4,7 @@ import styled from "styled-components"; import { stopRecording } from "../../api/recording"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { IconButton, Menu, MenuItem, Typography, Chip } from "@mui/material"; -import { AccountCircle, Logout, Clear } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, Language } from "@mui/icons-material"; import { useNavigate } from "react-router-dom"; import { AuthContext } from "../../context/auth"; import { SaveRecording } from "../molecules/SaveRecording"; @@ -159,7 +159,7 @@ export const NavBar: React.FC = ({ {t("logout")} - {/* Language dropdown */} + ) : ( <> @@ -190,7 +190,9 @@ export const NavBar: React.FC = ({ marginRight: "10px", }} > - {t("language")} + + +
string; } -export const columns: readonly Column[] = [ - { id: 'runStatus', label: 'Status', minWidth: 80 }, - { id: 'name', label: 'Robot Name', minWidth: 80 }, - { id: 'startedAt', label: 'Started at', minWidth: 80 }, - { id: 'finishedAt', label: 'Finished at', minWidth: 80 }, - { id: 'settings', label: 'Settings', minWidth: 80 }, - { id: 'delete', label: 'Delete', minWidth: 80 }, -]; - -export interface Data { +interface Data { id: number; status: string; name: string; @@ -58,15 +61,25 @@ interface RunsTableProps { runningRecordingName: string; } -export const RunsTable = ( - { currentInterpretationLog, abortRunHandler, runId, runningRecordingName }: RunsTableProps) => { +export const RunsTable: React.FC = ({ + currentInterpretationLog, + abortRunHandler, + runId, + runningRecordingName +}) => { + const { t } = useTranslation(); + + // Update column labels using translation if needed + const translatedColumns = columns.map(column => ({ + ...column, + label: t(`runstable.${column.id}`, column.label) + })); + const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); const [rows, setRows] = useState([]); - const [searchTerm, setSearchTerm] = useState(''); - const { notify, rerenderRuns, setRerenderRuns } = useGlobalInfoStore(); const handleChangePage = (event: unknown, newPage: number) => { @@ -86,16 +99,13 @@ export const RunsTable = ( const fetchRuns = async () => { const runs = await getStoredRuns(); if (runs) { - const parsedRows: Data[] = []; - runs.map((run: any, index) => { - parsedRows.push({ - id: index, - ...run, - }); - }); + const parsedRows: Data[] = runs.map((run: any, index: number) => ({ + id: index, + ...run, + })); setRows(parsedRows); } else { - notify('error', 'No runs found. Please try again.') + notify('error', 'No runs found. Please try again.'); } }; @@ -104,7 +114,7 @@ export const RunsTable = ( fetchRuns(); setRerenderRuns(false); } - }, [rerenderRuns]); + }, [rerenderRuns, rows.length, setRerenderRuns]); const handleDelete = () => { setRows([]); @@ -112,7 +122,6 @@ export const RunsTable = ( fetchRuns(); }; - // Filter rows based on search term const filteredRows = rows.filter((row) => row.name.toLowerCase().includes(searchTerm.toLowerCase()) @@ -120,7 +129,6 @@ export const RunsTable = ( // Group filtered rows by robot meta id const groupedRows = filteredRows.reduce((acc, row) => { - if (!acc[row.robotMetaId]) { acc[row.robotMetaId] = []; } @@ -132,11 +140,11 @@ export const RunsTable = ( - All Runs + {t('runstable.runs', 'Runs')} ( }> - {data[data.length - 1].name} - - {columns.map((column) => ( + {translatedColumns.map((column) => ( ); -}; +}; \ No newline at end of file diff --git a/src/pages/Register.tsx b/src/pages/Register.tsx index 57ec676a4..b1fb23e2d 100644 --- a/src/pages/Register.tsx +++ b/src/pages/Register.tsx @@ -83,7 +83,7 @@ const Register = () => { > logo - Create an Account + {t('register.title')} Date: Fri, 13 Dec 2024 21:20:25 +0530 Subject: [PATCH 004/238] feat: pass context script for webdriver --- .../classes/RemoteBrowser.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 04fb59b32..2dab103a6 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -225,6 +225,31 @@ export class RemoteBrowser { contextOptions.userAgent = browserUserAgent; this.context = await this.browser.newContext(contextOptions); + await this.context.addInitScript( + `const defaultGetter = Object.getOwnPropertyDescriptor( + Navigator.prototype, + "webdriver" + ).get; + defaultGetter.apply(navigator); + defaultGetter.toString(); + Object.defineProperty(Navigator.prototype, "webdriver", { + set: undefined, + enumerable: true, + configurable: true, + get: new Proxy(defaultGetter, { + apply: (target, thisArg, args) => { + Reflect.apply(target, thisArg, args); + return false; + }, + }), + }); + const patchedGetter = Object.getOwnPropertyDescriptor( + Navigator.prototype, + "webdriver" + ).get; + patchedGetter.apply(navigator); + patchedGetter.toString();` + ); this.currentPage = await this.context.newPage(); await this.setupPageEventListeners(this.currentPage); From cd05ddfb3c780aa26ec1e6108c4f173dafe26291 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 13 Dec 2024 21:21:00 +0530 Subject: [PATCH 005/238] chore: lint --- .../src/browser-management/classes/RemoteBrowser.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 2dab103a6..b19b5cbc9 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -104,7 +104,7 @@ export class RemoteBrowser { } catch { return url; } - } + } /** * Determines if a URL change is significant enough to emit @@ -130,11 +130,11 @@ export class RemoteBrowser { }); // Handle page load events with retry mechanism - page.on('load', async () => { + page.on('load', async () => { const injectScript = async (): Promise => { try { await page.waitForLoadState('networkidle', { timeout: 5000 }); - + await page.evaluate(getInjectableScript()); return true; } catch (error: any) { @@ -201,7 +201,7 @@ export class RemoteBrowser { const contextOptions: any = { viewport: { height: 400, width: 900 }, // recordVideo: { dir: 'videos/' } - // Force reduced motion to prevent animation issues + // Force reduced motion to prevent animation issues reducedMotion: 'reduce', // Force JavaScript to be enabled javaScriptEnabled: true, @@ -249,7 +249,7 @@ export class RemoteBrowser { ).get; patchedGetter.apply(navigator); patchedGetter.toString();` - ); + ); this.currentPage = await this.context.newPage(); await this.setupPageEventListeners(this.currentPage); @@ -481,7 +481,7 @@ export class RemoteBrowser { this.currentPage = newPage; if (this.currentPage) { await this.setupPageEventListeners(this.currentPage); - + this.client = await this.currentPage.context().newCDPSession(this.currentPage); await this.subscribeToScreencast(); } else { From c49e70a1eeab9ef569f1e41738bea8882915ec22 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 13 Dec 2024 22:04:35 +0530 Subject: [PATCH 006/238] chrome and chromium user agent --- server/src/browser-management/classes/RemoteBrowser.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index b19b5cbc9..e5d3217e8 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -220,8 +220,7 @@ export class RemoteBrowser { password: proxyOptions.password ? proxyOptions.password : undefined, }; } - const browserUserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.38 Safari/537.36"; - + const browserUserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.140 Chromium/131.0.6778.140 Safari/537.36"; contextOptions.userAgent = browserUserAgent; this.context = await this.browser.newContext(contextOptions); From b173ce3e98d9bcc2838de7ee257f3b8ee5e95a92 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 13 Dec 2024 22:05:51 +0530 Subject: [PATCH 007/238] chore: remove commented code --- .../classes/RemoteBrowser.ts | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index e5d3217e8..0299faf65 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -155,35 +155,6 @@ export class RemoteBrowser { * @returns {Promise} */ public initialize = async (userId: string): Promise => { - // const launchOptions = { - // headless: true, - // proxy: options.launchOptions?.proxy, - // chromiumSandbox: false, - // args: [ - // '--no-sandbox', - // '--disable-setuid-sandbox', - // '--headless=new', - // '--disable-gpu', - // '--disable-dev-shm-usage', - // '--disable-software-rasterizer', - // '--in-process-gpu', - // '--disable-infobars', - // '--single-process', - // '--no-zygote', - // '--disable-notifications', - // '--disable-extensions', - // '--disable-background-timer-throttling', - // ...(options.launchOptions?.args || []) - // ], - // env: { - // ...process.env, - // CHROMIUM_FLAGS: '--disable-gpu --no-sandbox --headless=new' - // } - // }; - // console.log('Launch options before:', options.launchOptions); - // this.browser = (await options.browser.launch(launchOptions)); - - // console.log('Launch options after:', options.launchOptions) this.browser = (await chromium.launch({ headless: true, })); @@ -253,9 +224,6 @@ export class RemoteBrowser { await this.setupPageEventListeners(this.currentPage); - // await this.currentPage.setExtraHTTPHeaders({ - // 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3' - // }); const blocker = await PlaywrightBlocker.fromLists(fetch, ['https://easylist.to/easylist/easylist.txt']); await blocker.enableBlockingInPage(this.currentPage); this.client = await this.currentPage.context().newCDPSession(this.currentPage); From 06184010ae1a789c86bc80d00cd082752fdd1444 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 14 Dec 2024 06:58:29 +0530 Subject: [PATCH 008/238] feat: args --- server/src/browser-management/classes/RemoteBrowser.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 0299faf65..9dc516908 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -157,6 +157,13 @@ export class RemoteBrowser { public initialize = async (userId: string): Promise => { this.browser = (await chromium.launch({ headless: true, + args: [ + "--disable-blink-features=AutomationControlled", + "--disable-web-security", + "--disable-features=IsolateOrigins,site-per-process", + "--disable-site-isolation-trials", + "--disable-extensions" + ], })); const proxyConfig = await getDecryptedProxyConfig(userId); let proxyOptions: { server: string, username?: string, password?: string } = { server: '' }; From 44693259257497deb6b285f54e64a0ae0ec2b7b1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 14 Dec 2024 10:49:52 +0530 Subject: [PATCH 009/238] chore: sync compose master <-> develop --- docker-compose.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 51a9f4eba..3c6e3a0f7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -64,8 +64,6 @@ services: - redis - minio volumes: - - ./server:/app/server # Mount server source code for hot reloading - - ./maxun-core:/app/maxun-core # Mount maxun-core for any shared code updates - /var/run/dbus:/var/run/dbus frontend: @@ -79,13 +77,10 @@ services: environment: PUBLIC_URL: ${PUBLIC_URL} BACKEND_URL: ${BACKEND_URL} - volumes: - - ./:/app # Mount entire frontend app directory for hot reloading - - /app/node_modules # Anonymous volume to prevent overwriting node_modules depends_on: - backend volumes: postgres_data: minio_data: - redis_data: + redis_data: \ No newline at end of file From 7f48464eea993f0d4468942cdeb77c87398191f8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 14 Dec 2024 18:35:38 +0530 Subject: [PATCH 010/238] feat: add page navigation timeout --- maxun-core/src/interpret.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/maxun-core/src/interpret.ts b/maxun-core/src/interpret.ts index d1cc8318d..848ddd768 100644 --- a/maxun-core/src/interpret.ts +++ b/maxun-core/src/interpret.ts @@ -365,7 +365,7 @@ export default class Interpreter extends EventEmitter { try { const newPage = await context.newPage(); await newPage.goto(link); - await newPage.waitForLoadState('networkidle'); + await newPage.waitForLoadState('domcontentloaded'); await this.runLoop(newPage, this.initializedWorkflow!); } catch (e) { // `runLoop` uses soft mode, so it recovers from it's own exceptions @@ -576,7 +576,7 @@ export default class Interpreter extends EventEmitter { } await Promise.all([ nextButton.dispatchEvent('click'), - page.waitForNavigation({ waitUntil: 'networkidle' }) + page.waitForNavigation({ waitUntil: 'domcontentloaded' }) ]); await page.waitForTimeout(1000); @@ -767,6 +767,8 @@ export default class Interpreter extends EventEmitter { public async run(page: Page, params?: ParamType): Promise { this.log('Starting the workflow.', Level.LOG); const context = page.context(); + + page.setDefaultNavigationTimeout(100000); // Check proxy settings from context options const contextOptions = (context as any)._options; From bdf908e37cdcb2200cb5c653a5149db279ce51aa Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 14 Dec 2024 18:36:59 +0530 Subject: [PATCH 011/238] feat: add domcontentloaded wait load state --- server/src/workflow-management/classes/Generator.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 57be015ed..2cde90e4c 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -189,7 +189,7 @@ export class WorkflowGenerator { * * This function also makes sure to add a waitForLoadState and a generated flag * action after every new action or pair added. The [waitForLoadState](https://playwright.dev/docs/api/class-frame#frame-wait-for-load-state) - * action waits for the networkidle event to be fired, + * action waits for the domcontentloaded event to be fired, * and the generated flag action is used for making pausing the interpretation possible. * * @param pair The pair to add to the workflow. @@ -217,7 +217,7 @@ export class WorkflowGenerator { if (pair.what[0].action !== 'waitForLoadState' && pair.what[0].action !== 'press') { pair.what.push({ action: 'waitForLoadState', - args: ['networkidle'], + args: ['domcontentloaded'], }); } this.workflowRecord.workflow[matchedIndex].what = this.workflowRecord.workflow[matchedIndex].what.concat(pair.what); @@ -232,7 +232,7 @@ export class WorkflowGenerator { if (pair.what[0].action !== 'waitForLoadState' && pair.what[0].action !== 'press') { pair.what.push({ action: 'waitForLoadState', - args: ['networkidle'], + args: ['domcontentloaded'], }); } if (this.generatedData.lastIndex === 0) { From f38230d1b4d45d266886679c3228d07d2f52d18d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 14 Dec 2024 20:30:24 +0530 Subject: [PATCH 012/238] feat: revert to networkidle for wait load state --- server/src/workflow-management/classes/Generator.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 2cde90e4c..57be015ed 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -189,7 +189,7 @@ export class WorkflowGenerator { * * This function also makes sure to add a waitForLoadState and a generated flag * action after every new action or pair added. The [waitForLoadState](https://playwright.dev/docs/api/class-frame#frame-wait-for-load-state) - * action waits for the domcontentloaded event to be fired, + * action waits for the networkidle event to be fired, * and the generated flag action is used for making pausing the interpretation possible. * * @param pair The pair to add to the workflow. @@ -217,7 +217,7 @@ export class WorkflowGenerator { if (pair.what[0].action !== 'waitForLoadState' && pair.what[0].action !== 'press') { pair.what.push({ action: 'waitForLoadState', - args: ['domcontentloaded'], + args: ['networkidle'], }); } this.workflowRecord.workflow[matchedIndex].what = this.workflowRecord.workflow[matchedIndex].what.concat(pair.what); @@ -232,7 +232,7 @@ export class WorkflowGenerator { if (pair.what[0].action !== 'waitForLoadState' && pair.what[0].action !== 'press') { pair.what.push({ action: 'waitForLoadState', - args: ['domcontentloaded'], + args: ['networkidle'], }); } if (this.generatedData.lastIndex === 0) { From 7ce7a1598c3c394d8107677859991257460755ee Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 14 Dec 2024 20:32:07 +0530 Subject: [PATCH 013/238] feat: check for selector visibility in getState --- maxun-core/src/interpret.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/maxun-core/src/interpret.ts b/maxun-core/src/interpret.ts index 848ddd768..e11ae255a 100644 --- a/maxun-core/src/interpret.ts +++ b/maxun-core/src/interpret.ts @@ -192,8 +192,8 @@ export default class Interpreter extends EventEmitter { // const actionable = async (selector: string): Promise => { // try { // const proms = [ - // page.isEnabled(selector, { timeout: 5000 }), - // page.isVisible(selector, { timeout: 5000 }), + // page.isEnabled(selector, { timeout: 10000 }), + // page.isVisible(selector, { timeout: 10000 }), // ]; // return await Promise.all(proms).then((bools) => bools.every((x) => x)); @@ -214,6 +214,17 @@ export default class Interpreter extends EventEmitter { // return []; // }), // ).then((x) => x.flat()); + + const presentSelectors: SelectorArray = await Promise.all( + selectors.map(async (selector) => { + try { + await page.waitForSelector(selector, { state: 'attached' }); + return [selector]; + } catch (e) { + return []; + } + }), + ).then((x) => x.flat()); const action = workflowCopy[workflowCopy.length - 1]; @@ -233,7 +244,7 @@ export default class Interpreter extends EventEmitter { ...p, [cookie.name]: cookie.value, }), {}), - selectors, + selectors: presentSelectors, }; } @@ -365,7 +376,7 @@ export default class Interpreter extends EventEmitter { try { const newPage = await context.newPage(); await newPage.goto(link); - await newPage.waitForLoadState('domcontentloaded'); + await newPage.waitForLoadState('networkidle'); await this.runLoop(newPage, this.initializedWorkflow!); } catch (e) { // `runLoop` uses soft mode, so it recovers from it's own exceptions @@ -576,7 +587,7 @@ export default class Interpreter extends EventEmitter { } await Promise.all([ nextButton.dispatchEvent('click'), - page.waitForNavigation({ waitUntil: 'domcontentloaded' }) + page.waitForNavigation({ waitUntil: 'networkidle' }) ]); await page.waitForTimeout(1000); From e22c019a0c6feed2b2c3e2ecb2aa4b749dd0f226 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 14 Dec 2024 22:30:50 +0530 Subject: [PATCH 014/238] feat: rotate user agents --- .../browser-management/classes/RemoteBrowser.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 9dc516908..05927b24c 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -148,6 +148,19 @@ export class RemoteBrowser { }); } + private getUserAgent() { + const userAgents = [ + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.140 Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:117.0) Gecko/20100101 Firefox/117.0', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.1938.81 Safari/537.36 Edg/116.0.1938.81', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.96 Safari/537.36 OPR/101.0.4843.25', + 'Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.62 Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:118.0) Gecko/20100101 Firefox/118.0', + ]; + + return userAgents[Math.floor(Math.random() * userAgents.length)]; + } + /** * An asynchronous constructor for asynchronously initialized properties. * Must be called right after creating an instance of RemoteBrowser class. @@ -198,9 +211,8 @@ export class RemoteBrowser { password: proxyOptions.password ? proxyOptions.password : undefined, }; } - const browserUserAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.140 Chromium/131.0.6778.140 Safari/537.36"; - contextOptions.userAgent = browserUserAgent; + contextOptions.userAgent = this.getUserAgent(); this.context = await this.browser.newContext(contextOptions); await this.context.addInitScript( `const defaultGetter = Object.getOwnPropertyDescriptor( From 6c15df78161969fdc46ea0af98fdcc19e2a5ed4f Mon Sep 17 00:00:00 2001 From: The Hague Centre for Strategic Studies <51345661+HCSS-StratBase@users.noreply.github.com> Date: Sat, 14 Dec 2024 19:46:21 +0100 Subject: [PATCH 015/238] Update README.md small addition to make the installation instructions more 'noob-proof' --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 38d0eebe8..b63cf8a7e 100644 --- a/README.md +++ b/README.md @@ -30,14 +30,15 @@ Maxun lets you train a robot in 2 minutes and scrape the web on auto-pilot. Web # Installation -1. First, create a file named `.env` in the root folder of the project -2. Example env file can be viewed [here](https://github.com/getmaxun/maxun/blob/master/ENVEXAMPLE). Copy all content of example env to your `.env` file. -3. Choose your installation method below +1. Create a root folder for your project (e.g. 'maxun') +2. Create a file named `.env` in the root folder of the project +3. Example env file can be viewed [here](https://github.com/getmaxun/maxun/blob/master/ENVEXAMPLE). Copy all content of example env to your `.env` file. +4. Choose your installation method below ### Docker Compose -1. Copy paste the [docker-compose.yml file](https://github.com/getmaxun/maxun/blob/master/docker-compose.yml) -2. Ensure you have setup the `.env` file -3. Run the command below +1. Copy paste the [docker-compose.yml file](https://github.com/getmaxun/maxun/blob/master/docker-compose.yml) into your root folder +2. Ensure you have setup the `.env` file in that same folder +3. Run the command below from a terminal ``` docker-compose up -d ``` From 320f24ec002256067c418f45efbb48258599c893 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 01:06:23 +0530 Subject: [PATCH 016/238] feat: shm & sandbox args --- server/src/browser-management/classes/RemoteBrowser.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 05927b24c..4b059cdaf 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -175,7 +175,9 @@ export class RemoteBrowser { "--disable-web-security", "--disable-features=IsolateOrigins,site-per-process", "--disable-site-isolation-trials", - "--disable-extensions" + "--disable-extensions", + "--no-sandbox", + "--disable-dev-shm-usage", ], })); const proxyConfig = await getDecryptedProxyConfig(userId); @@ -201,7 +203,7 @@ export class RemoteBrowser { // Disable hardware acceleration forcedColors: 'none', isMobile: false, - hasTouch: false + hasTouch: false, }; if (proxyOptions.server) { @@ -212,7 +214,6 @@ export class RemoteBrowser { }; } - contextOptions.userAgent = this.getUserAgent(); this.context = await this.browser.newContext(contextOptions); await this.context.addInitScript( `const defaultGetter = Object.getOwnPropertyDescriptor( From ffe87b0c7db7b0e6446c3f0fb2a5d67e313f29b8 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 01:06:45 +0530 Subject: [PATCH 017/238] feat: user getUserAgent() --- server/src/browser-management/classes/RemoteBrowser.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 4b059cdaf..31aceadaa 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -204,6 +204,7 @@ export class RemoteBrowser { forcedColors: 'none', isMobile: false, hasTouch: false, + userAgent: this.getUserAgent(), }; if (proxyOptions.server) { From e70145219eca9a092487db350487f4a6bb711906 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 04:58:13 +0530 Subject: [PATCH 018/238] feat: remove container tags --- server/src/workflow-management/selector.ts | 37 ---------------------- 1 file changed, 37 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 891c0e3ba..bde38300b 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -74,22 +74,10 @@ export const getElementInformation = async ( if (originalEl) { let element = originalEl; - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', - 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', - 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', - 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', - 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', - 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' - ]; while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); const childRect = element.getBoundingClientRect(); - if (!containerTags.includes(element.parentElement.tagName)) { - break; - } - const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && @@ -202,22 +190,10 @@ export const getRect = async (page: Page, coordinates: Coordinates, listSelector if (originalEl) { let element = originalEl; - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', - 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', - 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', - 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', - 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', - 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' - ]; while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); const childRect = element.getBoundingClientRect(); - if (!containerTags.includes(element.parentElement.tagName)) { - break; - } - const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && @@ -914,23 +890,10 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates let element = originalEl; - const containerTags = ['DIV', 'SECTION', 'ARTICLE', 'MAIN', 'HEADER', 'FOOTER', 'NAV', 'ASIDE', - 'ADDRESS', 'BLOCKQUOTE', 'DETAILS', 'DIALOG', 'FIGURE', 'FIGCAPTION', 'MAIN', 'MARK', 'SUMMARY', 'TIME', - 'TABLE', 'THEAD', 'TBODY', 'TFOOT', 'TR', 'TH', 'TD', 'CAPTION', 'COLGROUP', 'COL', 'FORM', 'FIELDSET', - 'LEGEND', 'LABEL', 'INPUT', 'BUTTON', 'SELECT', 'DATALIST', 'OPTGROUP', 'OPTION', 'TEXTAREA', 'OUTPUT', - 'PROGRESS', 'METER', 'DETAILS', 'SUMMARY', 'MENU', 'MENUITEM', 'MENUITEM', 'APPLET', 'EMBED', 'OBJECT', - 'PARAM', 'VIDEO', 'AUDIO', 'SOURCE', 'TRACK', 'CANVAS', 'MAP', 'AREA', 'SVG', 'IFRAME', 'FRAME', 'FRAMESET', - 'LI', 'UL', 'OL', 'DL', 'DT', 'DD', 'HR', 'P', 'PRE', 'LISTING', 'PLAINTEXT', 'A' - ]; - while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); const childRect = element.getBoundingClientRect(); - if (!containerTags.includes(element.parentElement.tagName)) { - break; - } - const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && From cb0965323e3a8f13483e198bb1e7dbf086a4481d Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 05:01:15 +0530 Subject: [PATCH 019/238] feat: accept getList in getRect and getElementInfo --- server/src/workflow-management/classes/Generator.ts | 6 +++--- server/src/workflow-management/selector.ts | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 57be015ed..2ab547532 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -541,7 +541,7 @@ export class WorkflowGenerator { * @returns {Promise} */ private generateSelector = async (page: Page, coordinates: Coordinates, action: ActionType) => { - const elementInfo = await getElementInformation(page, coordinates, this.listSelector); + const elementInfo = await getElementInformation(page, coordinates, this.listSelector, this.getList); const selectorBasedOnCustomAction = (this.getList === true) ? await getNonUniqueSelectors(page, coordinates) : await getSelectors(page, coordinates); @@ -569,9 +569,9 @@ export class WorkflowGenerator { * @returns {Promise} */ public generateDataForHighlighter = async (page: Page, coordinates: Coordinates) => { - const rect = await getRect(page, coordinates, this.listSelector); + const rect = await getRect(page, coordinates, this.listSelector, this.getList); const displaySelector = await this.generateSelector(page, coordinates, ActionType.Click); - const elementInfo = await getElementInformation(page, coordinates, this.listSelector); + const elementInfo = await getElementInformation(page, coordinates, this.listSelector, this.getList); if (rect) { if (this.getList === true) { if (this.listSelector !== '') { diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index bde38300b..fd25a617c 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -17,6 +17,7 @@ export const getElementInformation = async ( page: Page, coordinates: Coordinates, listSelector: string, + getList: boolean ) => { try { if (listSelector !== '') { @@ -155,7 +156,7 @@ export const getElementInformation = async ( * @category WorkflowManagement-Selectors * @returns {Promise} */ -export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string) => { +export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string, getList: boolean) => { try { if (listSelector !== '') { const rect = await page.evaluate( From ddb880df668e84ebce1d7731f6dda6aa2413a486 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 05:07:45 +0530 Subject: [PATCH 020/238] fix: capture text selection --- server/src/workflow-management/selector.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index fd25a617c..36b592a64 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -20,7 +20,7 @@ export const getElementInformation = async ( getList: boolean ) => { try { - if (listSelector !== '') { + if (!getList) { const elementInfo = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -158,7 +158,7 @@ export const getElementInformation = async ( */ export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string, getList: boolean) => { try { - if (listSelector !== '') { + if (!getList) { const rect = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; From 97e7c89105132d42864be52386e9971208f88d8f Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 05:13:08 +0530 Subject: [PATCH 021/238] feat: re-add listSelector empty check for child selection --- server/src/workflow-management/selector.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 36b592a64..699cb669d 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -20,7 +20,7 @@ export const getElementInformation = async ( getList: boolean ) => { try { - if (!getList) { + if (!getList || (getList && listSelector !== '')) { const elementInfo = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -158,7 +158,7 @@ export const getElementInformation = async ( */ export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string, getList: boolean) => { try { - if (!getList) { + if (!getList || (getList && listSelector !== '')) { const rect = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; From 0c3b1e3e53c4e52c7898a2f8637884c0f07e118a Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 15 Dec 2024 05:29:30 +0530 Subject: [PATCH 022/238] feat: paass listSelect --- .../workflow-management/classes/Generator.ts | 2 +- server/src/workflow-management/selector.ts | 40 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 2ab547532..31775261c 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -543,7 +543,7 @@ export class WorkflowGenerator { private generateSelector = async (page: Page, coordinates: Coordinates, action: ActionType) => { const elementInfo = await getElementInformation(page, coordinates, this.listSelector, this.getList); const selectorBasedOnCustomAction = (this.getList === true) - ? await getNonUniqueSelectors(page, coordinates) + ? await getNonUniqueSelectors(page, coordinates, this.listSelector) : await getSelectors(page, coordinates); const bestSelector = getBestSelectorForAction( diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 699cb669d..527a800f3 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -852,7 +852,7 @@ interface SelectorResult { * @returns {Promise} */ -export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates): Promise => { +export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates, listSelector: string): Promise => { try { const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { function getNonUniqueSelector(element: HTMLElement): string { @@ -891,24 +891,26 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates let element = originalEl; - while (element.parentElement) { - const parentRect = element.parentElement.getBoundingClientRect(); - const childRect = element.getBoundingClientRect(); - - const fullyContained = - parentRect.left <= childRect.left && - parentRect.right >= childRect.right && - parentRect.top <= childRect.top && - parentRect.bottom >= childRect.bottom; - - const significantOverlap = - (childRect.width * childRect.height) / - (parentRect.width * parentRect.height) > 0.5; - - if (fullyContained && significantOverlap) { - element = element.parentElement; - } else { - break; + if (listSelector === '') { + while (element.parentElement) { + const parentRect = element.parentElement.getBoundingClientRect(); + const childRect = element.getBoundingClientRect(); + + const fullyContained = + parentRect.left <= childRect.left && + parentRect.right >= childRect.right && + parentRect.top <= childRect.top && + parentRect.bottom >= childRect.bottom; + + const significantOverlap = + (childRect.width * childRect.height) / + (parentRect.width * parentRect.height) > 0.5; + + if (fullyContained && significantOverlap) { + element = element.parentElement; + } else { + break; + } } } From e1476935db354b7030eced9447c280241defb713 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 16 Dec 2024 07:25:13 +0530 Subject: [PATCH 023/238] fix: dont pass listSelector to non unique --- server/src/workflow-management/classes/Generator.ts | 2 +- server/src/workflow-management/selector.ts | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 31775261c..2ab547532 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -543,7 +543,7 @@ export class WorkflowGenerator { private generateSelector = async (page: Page, coordinates: Coordinates, action: ActionType) => { const elementInfo = await getElementInformation(page, coordinates, this.listSelector, this.getList); const selectorBasedOnCustomAction = (this.getList === true) - ? await getNonUniqueSelectors(page, coordinates, this.listSelector) + ? await getNonUniqueSelectors(page, coordinates) : await getSelectors(page, coordinates); const bestSelector = getBestSelectorForAction( diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 527a800f3..070a897dc 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -20,7 +20,8 @@ export const getElementInformation = async ( getList: boolean ) => { try { - if (!getList || (getList && listSelector !== '')) { + console.log(`List Selector Value From EL INFO: ->> ${listSelector !== '' ? listSelector: 'It is empty'}`); + if (!getList ||listSelector !== '') { const elementInfo = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -158,7 +159,7 @@ export const getElementInformation = async ( */ export const getRect = async (page: Page, coordinates: Coordinates, listSelector: string, getList: boolean) => { try { - if (!getList || (getList && listSelector !== '')) { + if (!getList || listSelector !== '') { const rect = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -852,7 +853,7 @@ interface SelectorResult { * @returns {Promise} */ -export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates, listSelector: string): Promise => { +export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates): Promise => { try { const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { function getNonUniqueSelector(element: HTMLElement): string { @@ -891,7 +892,7 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates let element = originalEl; - if (listSelector === '') { + // if (listSelector === '') { while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); const childRect = element.getBoundingClientRect(); @@ -912,7 +913,7 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates break; } } - } + // } const generalSelector = getSelectorPath(element); return { From 4a9496053177663e4081850cf9db57742899a578 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 16 Dec 2024 08:22:21 +0530 Subject: [PATCH 024/238] feat: push parentSelector --- server/src/workflow-management/selector.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 070a897dc..e326f21b4 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -968,6 +968,7 @@ export const getChildSelectors = async (page: Page, parentSelector: string): Pro const childPath = getSelectorPath(child); if (childPath) { selectors.push(childPath); // Add direct child path + selectors.push(parentSelector) selectors = selectors.concat(getAllDescendantSelectors(child)); // Recursively process descendants } } From 23ac1340840a33d307f3730a1ecf0485b06a80b8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Mon, 16 Dec 2024 15:55:55 +0530 Subject: [PATCH 025/238] fix: add pair to workflow before decision socket emission --- .../workflow-management/classes/Generator.ts | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 57be015ed..9fab04d35 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -140,19 +140,22 @@ export class WorkflowGenerator { socket.on('decision', async ({ pair, actionType, decision }) => { const id = browserPool.getActiveBrowserId(); if (id) { - const activeBrowser = browserPool.getRemoteBrowser(id); - const currentPage = activeBrowser?.getCurrentPage(); - if (decision) { + // const activeBrowser = browserPool.getRemoteBrowser(id); + // const currentPage = activeBrowser?.getCurrentPage(); + if (!decision) { switch (actionType) { case 'customAction': - pair.where.selectors = [this.generatedData.lastUsedSelector]; + // pair.where.selectors = [this.generatedData.lastUsedSelector]; + pair.where.selectors = pair.where.selectors.filter( + (selector: string) => selector !== this.generatedData.lastUsedSelector + ); break; default: break; } } - if (currentPage) { - await this.addPairToWorkflowAndNotifyClient(pair, currentPage); - } + // if (currentPage) { + // await this.addPairToWorkflowAndNotifyClient(pair, currentPage); + // } } }) socket.on('updatePair', (data) => { @@ -360,6 +363,8 @@ export class WorkflowGenerator { }], } + await this.addPairToWorkflowAndNotifyClient(pair, page); + if (this.generatedData.lastUsedSelector) { const elementInfo = await this.getLastUsedSelectorInfo(page, this.generatedData.lastUsedSelector); @@ -372,9 +377,7 @@ export class WorkflowGenerator { innerText: elementInfo.innerText, } }); - } else { - await this.addPairToWorkflowAndNotifyClient(pair, page); - } + } }; /** From 94df79404011d99cc6cc5d80bb1c77208f9abcc5 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 17 Dec 2024 02:48:14 +0530 Subject: [PATCH 026/238] feat: conditionally compute non unique --- server/src/workflow-management/selector.ts | 53 ++++++++++++++++++++-- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index e326f21b4..60f5bdbdc 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -20,8 +20,7 @@ export const getElementInformation = async ( getList: boolean ) => { try { - console.log(`List Selector Value From EL INFO: ->> ${listSelector !== '' ? listSelector: 'It is empty'}`); - if (!getList ||listSelector !== '') { + if (!getList || listSelector !== '') { const elementInfo = await page.evaluate( async ({ x, y }) => { const el = document.elementFromPoint(x, y) as HTMLElement; @@ -853,8 +852,10 @@ interface SelectorResult { * @returns {Promise} */ -export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates): Promise => { +export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates, listSelector: string): Promise => { try { + if (!listSelector) { + console.log(`NON UNIQUE: MODE 1`) const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { function getNonUniqueSelector(element: HTMLElement): string { let selector = element.tagName.toLowerCase(); @@ -920,8 +921,54 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates generalSelector, }; }, coordinates); + return selectors || { generalSelector: '' }; + } else { + console.log(`NON UNIQUE: MODE 2`) + const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { + function getNonUniqueSelector(element: HTMLElement): string { + let selector = element.tagName.toLowerCase(); + + if (element.className) { + const classes = element.className.split(/\s+/).filter((cls: string) => Boolean(cls)); + if (classes.length > 0) { + const validClasses = classes.filter((cls: string) => !cls.startsWith('!') && !cls.includes(':')); + if (validClasses.length > 0) { + selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.'); + } + } + } + + return selector; + } + + function getSelectorPath(element: HTMLElement | null): string { + const path: string[] = []; + let depth = 0; + const maxDepth = 2; + while (element && element !== document.body && depth < maxDepth) { + const selector = getNonUniqueSelector(element); + path.unshift(selector); + element = element.parentElement; + depth++; + } + + return path.join(' > '); + } + + const originalEl = document.elementFromPoint(x, y) as HTMLElement; + if (!originalEl) return null; + + let element = originalEl; + + const generalSelector = getSelectorPath(element); + return { + generalSelector, + }; + }, coordinates); return selectors || { generalSelector: '' }; + } + } catch (error) { console.error('Error in getNonUniqueSelectors:', error); return { generalSelector: '' }; From 52b767188eedd3ef3c3053a3e50d054fb9b35e44 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 17 Dec 2024 02:48:38 +0530 Subject: [PATCH 027/238] feat: !push parentSelector --- server/src/workflow-management/selector.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 60f5bdbdc..9c62139bf 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -1015,7 +1015,6 @@ export const getChildSelectors = async (page: Page, parentSelector: string): Pro const childPath = getSelectorPath(child); if (childPath) { selectors.push(childPath); // Add direct child path - selectors.push(parentSelector) selectors = selectors.concat(getAllDescendantSelectors(child)); // Recursively process descendants } } From 647cd62e32fba8fc55084dbacfef6029f071d076 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Tue, 17 Dec 2024 11:37:05 +0530 Subject: [PATCH 028/238] feat: add listSelector param --- server/src/workflow-management/classes/Generator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 2ab547532..31775261c 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -543,7 +543,7 @@ export class WorkflowGenerator { private generateSelector = async (page: Page, coordinates: Coordinates, action: ActionType) => { const elementInfo = await getElementInformation(page, coordinates, this.listSelector, this.getList); const selectorBasedOnCustomAction = (this.getList === true) - ? await getNonUniqueSelectors(page, coordinates) + ? await getNonUniqueSelectors(page, coordinates, this.listSelector) : await getSelectors(page, coordinates); const bestSelector = getBestSelectorForAction( From a9dc4c8f4ceeca8abe45268331b1369d4a1cbbb9 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Tue, 17 Dec 2024 12:21:56 +0530 Subject: [PATCH 029/238] feat: add conditional check to collect matching classes --- maxun-core/src/browserSide/scraper.js | 95 ++++++++++++++++++--------- 1 file changed, 63 insertions(+), 32 deletions(-) diff --git a/maxun-core/src/browserSide/scraper.js b/maxun-core/src/browserSide/scraper.js index 09b6578be..a2009d789 100644 --- a/maxun-core/src/browserSide/scraper.js +++ b/maxun-core/src/browserSide/scraper.js @@ -265,41 +265,72 @@ function scrapableHeuristics(maxCountPerPage = 50, minArea = 20000, scrolls = 3, const scrapedData = []; while (scrapedData.length < limit) { - // Get all parent elements matching the listSelector - const parentElements = Array.from(document.querySelectorAll(listSelector)); - - // Iterate through each parent element - for (const parent of parentElements) { - if (scrapedData.length >= limit) break; - const record = {}; - - // For each field, select the corresponding element within the parent - for (const [label, { selector, attribute }] of Object.entries(fields)) { - const fieldElement = parent.querySelector(selector); - - if (fieldElement) { - if (attribute === 'innerText') { - record[label] = fieldElement.innerText.trim(); - } else if (attribute === 'innerHTML') { - record[label] = fieldElement.innerHTML.trim(); - } else if (attribute === 'src') { - // Handle relative 'src' URLs - const src = fieldElement.getAttribute('src'); - record[label] = src ? new URL(src, window.location.origin).href : null; - } else if (attribute === 'href') { - // Handle relative 'href' URLs - const href = fieldElement.getAttribute('href'); - record[label] = href ? new URL(href, window.location.origin).href : null; - } else { - record[label] = fieldElement.getAttribute(attribute); + let parentElements = Array.from(document.querySelectorAll(listSelector)); + + // If we only got one element or none, try a more generic approach + if (limit > 1 && parentElements.length <= 1) { + const [containerSelector, _] = listSelector.split('>').map(s => s.trim()); + const container = document.querySelector(containerSelector); + + if (container) { + const allChildren = Array.from(container.children); + + const firstMatch = document.querySelector(listSelector); + if (firstMatch) { + // Get classes from the first matching element + const firstMatchClasses = Array.from(firstMatch.classList); + + // Find similar elements by matching most of their classes + parentElements = allChildren.filter(element => { + const elementClasses = Array.from(element.classList); + + // Element should share at least 70% of classes with the first match + const commonClasses = firstMatchClasses.filter(cls => + elementClasses.includes(cls)); + return commonClasses.length >= Math.floor(firstMatchClasses.length * 0.7); + }); + } } - } } - scrapedData.push(record); - } + + // Iterate through each parent element + for (const parent of parentElements) { + if (scrapedData.length >= limit) break; + const record = {}; + + // For each field, select the corresponding element within the parent + for (const [label, { selector, attribute }] of Object.entries(fields)) { + const fieldElement = parent.querySelector(selector); + + if (fieldElement) { + if (attribute === 'innerText') { + record[label] = fieldElement.innerText.trim(); + } else if (attribute === 'innerHTML') { + record[label] = fieldElement.innerHTML.trim(); + } else if (attribute === 'src') { + // Handle relative 'src' URLs + const src = fieldElement.getAttribute('src'); + record[label] = src ? new URL(src, window.location.origin).href : null; + } else if (attribute === 'href') { + // Handle relative 'href' URLs + const href = fieldElement.getAttribute('href'); + record[label] = href ? new URL(href, window.location.origin).href : null; + } else { + record[label] = fieldElement.getAttribute(attribute); + } + } + } + scrapedData.push(record); + } + + // If we've processed all available elements and still haven't reached the limit, + // break to avoid infinite loop + if (parentElements.length === 0 || scrapedData.length >= parentElements.length) { + break; + } } - return scrapedData - }; + return scrapedData; +}; /** From e34cfda770d9ff8c0c17cb6418c085ade066e7ec Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Tue, 17 Dec 2024 21:55:24 +0530 Subject: [PATCH 030/238] fix: skip click action if selector not visible --- maxun-core/src/interpret.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/maxun-core/src/interpret.ts b/maxun-core/src/interpret.ts index d1cc8318d..ef06d1abe 100644 --- a/maxun-core/src/interpret.ts +++ b/maxun-core/src/interpret.ts @@ -506,7 +506,11 @@ export default class Interpreter extends EventEmitter { try { await executeAction(invokee, methodName, step.args); } catch (error) { - await executeAction(invokee, methodName, [step.args[0], { force: true }]); + try{ + await executeAction(invokee, methodName, [step.args[0], { force: true }]); + } catch (error) { + continue + } } } else { await executeAction(invokee, methodName, step.args); From 0783cbc1c5679c88ea6973a4a0dd831dcae7b8ba Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Wed, 18 Dec 2024 18:17:50 +0530 Subject: [PATCH 031/238] feat: add date selection handler --- .../workflow-management/classes/Generator.ts | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 213a0e867..06eac494e 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -1,4 +1,4 @@ -import { Action, ActionType, Coordinates, TagName } from "../../types"; +import { Action, ActionType, Coordinates, TagName, DatePickerEventData } from "../../types"; import { WhereWhatPair, WorkflowFile } from 'maxun-core'; import logger from "../../logger"; import { Socket } from "socket.io"; @@ -255,6 +255,25 @@ export class WorkflowGenerator { logger.log('info', `Workflow emitted`); }; + public onDateSelection = async (page: Page, data: DatePickerEventData) => { + const { selector, value } = data; + + try { + await page.fill(selector, value); + } catch (error) { + console.error("Failed to fill date value:", error); + } + + const pair: WhereWhatPair = { + where: { url: this.getBestUrl(page.url()) }, + what: [{ + action: 'fill', + args: [selector, value], + }], + }; + + await this.addPairToWorkflowAndNotifyClient(pair, page); + }; /** * Generates a pair for the click event. @@ -266,6 +285,22 @@ export class WorkflowGenerator { let where: WhereWhatPair["where"] = { url: this.getBestUrl(page.url()) }; const selector = await this.generateSelector(page, coordinates, ActionType.Click); logger.log('debug', `Element's selector: ${selector}`); + + // Check if clicked element is a date input + const isDateInput = await page.evaluate(({x, y}) => { + const element = document.elementFromPoint(x, y); + return element instanceof HTMLInputElement && element.type === 'date'; + }, coordinates); + + if (isDateInput) { + // Notify client to show datepicker overlay + this.socket.emit('showDatePicker', { + coordinates, + selector + }); + return; + } + //const element = await getElementMouseIsOver(page, coordinates); //logger.log('debug', `Element: ${JSON.stringify(element, null, 2)}`); if (selector) { From 7ac79dc31c7ffa26d94d4b58f9d50088e238fca7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Wed, 18 Dec 2024 18:19:05 +0530 Subject: [PATCH 032/238] feat: add date selection event handlers --- .../src/browser-management/inputHandlers.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/server/src/browser-management/inputHandlers.ts b/server/src/browser-management/inputHandlers.ts index d6902b3f3..2e722e9de 100644 --- a/server/src/browser-management/inputHandlers.ts +++ b/server/src/browser-management/inputHandlers.ts @@ -6,7 +6,7 @@ import { Socket } from 'socket.io'; import logger from "../logger"; -import { Coordinates, ScrollDeltas, KeyboardInput } from '../types'; +import { Coordinates, ScrollDeltas, KeyboardInput, DatePickerEventData } from '../types'; import { browserPool } from "../server"; import { WorkflowGenerator } from "../workflow-management/classes/Generator"; import { Page } from "playwright"; @@ -223,6 +223,23 @@ const handleKeydown = async (generator: WorkflowGenerator, page: Page, { key, co logger.log('debug', `Key ${key} pressed`); }; +/** + * Handles the date selection event. + * @param generator - the workflow generator {@link Generator} + * @param page - the active page of the remote browser + * @param data - the data of the date selection event {@link DatePickerEventData} + * @category BrowserManagement + */ +const handleDateSelection = async (generator: WorkflowGenerator, page: Page, data: DatePickerEventData) => { + await generator.onDateSelection(page, data); + logger.log('debug', `Date ${data.value} selected`); +} + +const onDateSelection = async (data: DatePickerEventData) => { + logger.log('debug', 'Handling date selection event emitted from client'); + await handleWrapper(handleDateSelection, data); +} + /** * A wrapper function for handling the keyup event. * @param keyboardInput - the keyboard input of the keyup event @@ -378,6 +395,7 @@ const registerInputHandlers = (socket: Socket) => { socket.on("input:refresh", onRefresh); socket.on("input:back", onGoBack); socket.on("input:forward", onGoForward); + socket.on("input:date", onDateSelection); socket.on("action", onGenerateAction); }; From 7eea077e70124cc9a24faaa768d7752305158685 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Wed, 18 Dec 2024 18:21:05 +0530 Subject: [PATCH 033/238] feat: add interface to hanle date picker event data --- server/src/types/index.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/src/types/index.ts b/server/src/types/index.ts index 4fe761f12..f2e327efa 100644 --- a/server/src/types/index.ts +++ b/server/src/types/index.ts @@ -20,6 +20,16 @@ export interface Coordinates { y: number; } +/** + * interface to handle date picker events. + * @category Types + */ +export interface DatePickerEventData { + coordinates: Coordinates; + selector: string; + value: string; +} + /** * Holds the deltas of a wheel/scroll event. * @category Types From ec4d1acfa27c9c0ff5ef1fa6ae5415ecad6ebf15 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Wed, 18 Dec 2024 18:22:51 +0530 Subject: [PATCH 034/238] feat: trigger socket event to display date picker --- src/components/atoms/canvas.tsx | 35 +++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/components/atoms/canvas.tsx b/src/components/atoms/canvas.tsx index 1dd88e190..84d6a620b 100644 --- a/src/components/atoms/canvas.tsx +++ b/src/components/atoms/canvas.tsx @@ -3,6 +3,7 @@ import { useSocketStore } from '../../context/socket'; import { getMappedCoordinates } from "../../helpers/inputHelpers"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { useActionContext } from '../../context/browserActions'; +import DatePicker from './DatePicker'; interface CreateRefCallback { (ref: React.RefObject): void; @@ -31,6 +32,11 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { const getTextRef = useRef(getText); const getListRef = useRef(getList); + const [datePickerInfo, setDatePickerInfo] = React.useState<{ + coordinates: Coordinates; + selector: string; + } | null>(null); + const notifyLastAction = (action: string) => { if (lastAction !== action) { setLastAction(action); @@ -44,6 +50,28 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { getListRef.current = getList; }, [getText, getList]); + useEffect(() => { + if (socket) { + socket.on('showDatePicker', (info: {coordinates: Coordinates, selector: string}) => { + setDatePickerInfo(info); + }); + + return () => { + socket.off('showDatePicker'); + }; + } + }, [socket]); + + const handleDateSelect = (value: string) => { + if (socket && datePickerInfo) { + socket.emit('input:date', { + selector: datePickerInfo.selector, + value + }); + setDatePickerInfo(null); + } + }; + const onMouseEvent = useCallback((event: MouseEvent) => { if (socket && canvasRef.current) { // Get the canvas bounding rectangle @@ -146,6 +174,13 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { width={900} style={{ display: 'block' }} /> + {datePickerInfo && ( + setDatePickerInfo(null)} + /> + )} ); From 9ee54d118b522d87c7e37791e69f3a6496f53489 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Wed, 18 Dec 2024 18:23:56 +0530 Subject: [PATCH 035/238] feat: rm onHandleSelct callback function --- src/components/atoms/canvas.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/atoms/canvas.tsx b/src/components/atoms/canvas.tsx index 84d6a620b..13966abd2 100644 --- a/src/components/atoms/canvas.tsx +++ b/src/components/atoms/canvas.tsx @@ -62,16 +62,6 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { } }, [socket]); - const handleDateSelect = (value: string) => { - if (socket && datePickerInfo) { - socket.emit('input:date', { - selector: datePickerInfo.selector, - value - }); - setDatePickerInfo(null); - } - }; - const onMouseEvent = useCallback((event: MouseEvent) => { if (socket && canvasRef.current) { // Get the canvas bounding rectangle From 2e301924226fda12ce8fea82828b3eaa4c2976c6 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Wed, 18 Dec 2024 18:24:51 +0530 Subject: [PATCH 036/238] feat: add date picker component to input date --- src/components/atoms/DatePicker.tsx | 74 +++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/components/atoms/DatePicker.tsx diff --git a/src/components/atoms/DatePicker.tsx b/src/components/atoms/DatePicker.tsx new file mode 100644 index 000000000..30d3b8692 --- /dev/null +++ b/src/components/atoms/DatePicker.tsx @@ -0,0 +1,74 @@ +import React, { useState } from 'react'; +import { useSocketStore } from '../../context/socket'; +import { Coordinates } from './canvas'; + +interface DatePickerProps { + coordinates: Coordinates; + selector: string; + onClose: () => void; +} + +const DatePicker: React.FC = ({ coordinates, selector, onClose }) => { + const { socket } = useSocketStore(); + const [selectedDate, setSelectedDate] = useState(''); + + const handleDateChange = (e: React.ChangeEvent) => { + setSelectedDate(e.target.value); + }; + + const handleConfirm = () => { + if (socket && selectedDate) { + socket.emit('input:date', { + selector, + value: selectedDate + }); + onClose(); + } + }; + + return ( +
+
+ +
+ + +
+
+
+ ); +}; + +export default DatePicker; \ No newline at end of file From 14079fa0f89029502e6c3671aab0d9232e17e5a9 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 12:13:17 +0530 Subject: [PATCH 037/238] feat: date input check using element information --- server/src/workflow-management/classes/Generator.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 06eac494e..96645de0a 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -286,11 +286,11 @@ export class WorkflowGenerator { const selector = await this.generateSelector(page, coordinates, ActionType.Click); logger.log('debug', `Element's selector: ${selector}`); + const elementInfo = await getElementInformation(page, coordinates, '', false); + console.log("Element info: ", elementInfo); + // Check if clicked element is a date input - const isDateInput = await page.evaluate(({x, y}) => { - const element = document.elementFromPoint(x, y); - return element instanceof HTMLInputElement && element.type === 'date'; - }, coordinates); + const isDateInput = elementInfo?.tagName === 'INPUT' && elementInfo?.attributes?.type === 'date'; if (isDateInput) { // Notify client to show datepicker overlay From a6ed8c67b8b19e7d684e89f4e2985947a48d4522 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 12:14:08 +0530 Subject: [PATCH 038/238] feat: check for select type and emit dropdown socket event --- .../workflow-management/classes/Generator.ts | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 96645de0a..a221a47b9 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -289,6 +289,45 @@ export class WorkflowGenerator { const elementInfo = await getElementInformation(page, coordinates, '', false); console.log("Element info: ", elementInfo); + // Check if clicked element is a select dropdown + const isDropdown = elementInfo?.tagName === 'SELECT'; + + if (isDropdown && elementInfo.innerHTML) { + // Parse options from innerHTML + const options = elementInfo.innerHTML + .split(' { + const valueMatch = optionHtml.match(/value="([^"]*)"/); + const disabledMatch = optionHtml.includes('disabled="disabled"'); + const selectedMatch = optionHtml.includes('selected="selected"'); + + // Extract text content between > and + const textMatch = optionHtml.match(/>([^<]*) Date: Thu, 19 Dec 2024 12:23:13 +0530 Subject: [PATCH 039/238] feat: add dropdown selection action pair to workflow --- .../workflow-management/classes/Generator.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index a221a47b9..3395e9a16 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -275,6 +275,26 @@ export class WorkflowGenerator { await this.addPairToWorkflowAndNotifyClient(pair, page); }; + public onDropdownSelection = async (page: Page, data: { selector: string, value: string }) => { + const { selector, value } = data; + + try { + await page.selectOption(selector, value); + } catch (error) { + console.error("Failed to fill date value:", error); + } + + const pair: WhereWhatPair = { + where: { url: this.getBestUrl(page.url()) }, + what: [{ + action: 'selectOption', + args: [selector, value], + }], + }; + + await this.addPairToWorkflowAndNotifyClient(pair, page); + }; + /** * Generates a pair for the click event. * @param coordinates The coordinates of the click event. From d8b5ae4113d5a4201680e4e23ff6721708ec0199 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 12:24:19 +0530 Subject: [PATCH 040/238] feat: add dropdown selection handler functions and register socket event --- server/src/browser-management/inputHandlers.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/src/browser-management/inputHandlers.ts b/server/src/browser-management/inputHandlers.ts index 2e722e9de..4b37480f2 100644 --- a/server/src/browser-management/inputHandlers.ts +++ b/server/src/browser-management/inputHandlers.ts @@ -240,6 +240,16 @@ const onDateSelection = async (data: DatePickerEventData) => { await handleWrapper(handleDateSelection, data); } +const handleDropdownSelection = async (generator: WorkflowGenerator, page: Page, data: { selector: string, value: string }) => { + await generator.onDropdownSelection(page, data); + logger.log('debug', `Dropdown value ${data.value} selected`); +} + +const onDropdownSelection = async (data: { selector: string, value: string }) => { + logger.log('debug', 'Handling dropdown selection event emitted from client'); + await handleWrapper(handleDropdownSelection, data); +} + /** * A wrapper function for handling the keyup event. * @param keyboardInput - the keyboard input of the keyup event @@ -396,6 +406,7 @@ const registerInputHandlers = (socket: Socket) => { socket.on("input:back", onGoBack); socket.on("input:forward", onGoForward); socket.on("input:date", onDateSelection); + socket.on("input:dropdown", onDropdownSelection); socket.on("action", onGenerateAction); }; From 7bd7a84173d47be16a0f828a1067e7fca7a2ed8d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 14:04:05 +0530 Subject: [PATCH 041/238] feat: tigger socket event to display dropdown --- src/components/atoms/canvas.tsx | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/components/atoms/canvas.tsx b/src/components/atoms/canvas.tsx index 13966abd2..fc778963b 100644 --- a/src/components/atoms/canvas.tsx +++ b/src/components/atoms/canvas.tsx @@ -4,6 +4,7 @@ import { getMappedCoordinates } from "../../helpers/inputHelpers"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { useActionContext } from '../../context/browserActions'; import DatePicker from './DatePicker'; +import Dropdown from './Dropdown'; interface CreateRefCallback { (ref: React.RefObject): void; @@ -37,6 +38,17 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { selector: string; } | null>(null); + const [dropdownInfo, setDropdownInfo] = React.useState<{ + coordinates: Coordinates; + selector: string; + options: Array<{ + value: string; + text: string; + disabled: boolean; + selected: boolean; + }>; + } | null>(null); + const notifyLastAction = (action: string) => { if (lastAction !== action) { setLastAction(action); @@ -56,8 +68,22 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { setDatePickerInfo(info); }); + socket.on('showDropdown', (info: { + coordinates: Coordinates, + selector: string, + options: Array<{ + value: string; + text: string; + disabled: boolean; + selected: boolean; + }>; + }) => { + setDropdownInfo(info); + }); + return () => { socket.off('showDatePicker'); + socket.off('showDropdown'); }; } }, [socket]); @@ -171,6 +197,14 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { onClose={() => setDatePickerInfo(null)} /> )} + {dropdownInfo && ( + setDropdownInfo(null)} + /> + )} ); From 13b92ee5dce7d7e33e3e0f60c608e202187f01fb Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 14:05:02 +0530 Subject: [PATCH 042/238] feat: add dropdown component to input dropdown --- src/components/atoms/Dropdown.tsx | 85 +++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 src/components/atoms/Dropdown.tsx diff --git a/src/components/atoms/Dropdown.tsx b/src/components/atoms/Dropdown.tsx new file mode 100644 index 000000000..c7ead64b1 --- /dev/null +++ b/src/components/atoms/Dropdown.tsx @@ -0,0 +1,85 @@ +import React, { useState } from 'react'; +import { useSocketStore } from '../../context/socket'; +import { Coordinates } from './canvas'; + +interface DropdownProps { + coordinates: Coordinates; + selector: string; + options: Array<{ + value: string; + text: string; + disabled: boolean; + selected: boolean; + }>; + onClose: () => void; +} + +const Dropdown = ({ coordinates, selector, options, onClose }: DropdownProps) => { + const { socket } = useSocketStore(); + const [hoveredIndex, setHoveredIndex] = useState(null); + + const handleSelect = (value: string) => { + if (socket) { + socket.emit('input:dropdown', { selector, value }); + } + onClose(); + }; + + const containerStyle: React.CSSProperties = { + position: 'absolute', + left: coordinates.x, + top: coordinates.y, + zIndex: 1000, + width: '200px', + backgroundColor: 'white', + border: '1px solid rgb(169, 169, 169)', + boxShadow: '0 2px 4px rgba(0,0,0,0.15)', + }; + + const scrollContainerStyle: React.CSSProperties = { + maxHeight: '180px', + overflowY: 'auto', + overflowX: 'hidden', + }; + + const getOptionStyle = (option: any, index: number): React.CSSProperties => ({ + fontSize: '13.333px', + lineHeight: '18px', + padding: '0 3px', + cursor: option.disabled ? 'default' : 'default', + backgroundColor: hoveredIndex === index ? '#0078D7' : + option.selected ? '#0078D7' : + option.disabled ? '#f8f8f8' : 'white', + color: (hoveredIndex === index || option.selected) ? 'white' : + option.disabled ? '#a0a0a0' : 'black', + userSelect: 'none', + }); + + return ( +
+
e.stopPropagation()} + > +
+ {options.map((option, index) => ( +
!option.disabled && setHoveredIndex(index)} + onMouseLeave={() => setHoveredIndex(null)} + onClick={() => !option.disabled && handleSelect(option.value)} + > + {option.text} +
+ ))} +
+
+
+ ); +}; + +export default Dropdown; \ No newline at end of file From 947a6b75cb9d2d431d23ecfd98ec20cc1a27e855 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 16:16:47 +0530 Subject: [PATCH 043/238] feat: check for time input field and emit socket event --- .../workflow-management/classes/Generator.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 3395e9a16..9ff4922e5 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -295,6 +295,26 @@ export class WorkflowGenerator { await this.addPairToWorkflowAndNotifyClient(pair, page); }; + public onTimeSelection = async (page: Page, data: { selector: string, value: string }) => { + const { selector, value } = data; + + try { + await page.fill(selector, value); + } catch (error) { + console.error("Failed to set time value:", error); + } + + const pair: WhereWhatPair = { + where: { url: this.getBestUrl(page.url()) }, + what: [{ + action: 'fill', + args: [selector, value], + }], + }; + + await this.addPairToWorkflowAndNotifyClient(pair, page); + }; + /** * Generates a pair for the click event. * @param coordinates The coordinates of the click event. @@ -360,6 +380,16 @@ export class WorkflowGenerator { return; } + const isTimeInput = elementInfo?.tagName === 'INPUT' && elementInfo?.attributes?.type === 'time'; + + if (isTimeInput) { + this.socket.emit('showTimePicker', { + coordinates, + selector + }); + return; + } + //const element = await getElementMouseIsOver(page, coordinates); //logger.log('debug', `Element: ${JSON.stringify(element, null, 2)}`); if (selector) { From 0b2d099dc0348af577762aa2588250e2c8c6202a Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 16:25:48 +0530 Subject: [PATCH 044/238] feat: add time selection event handlers --- server/src/browser-management/inputHandlers.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/src/browser-management/inputHandlers.ts b/server/src/browser-management/inputHandlers.ts index 4b37480f2..982e18de8 100644 --- a/server/src/browser-management/inputHandlers.ts +++ b/server/src/browser-management/inputHandlers.ts @@ -250,6 +250,16 @@ const onDropdownSelection = async (data: { selector: string, value: string }) => await handleWrapper(handleDropdownSelection, data); } +const handleTimeSelection = async (generator: WorkflowGenerator, page: Page, data: { selector: string, value: string }) => { + await generator.onTimeSelection(page, data); + logger.log('debug', `Time value ${data.value} selected`); +} + +const onTimeSelection = async (data: { selector: string, value: string }) => { + logger.log('debug', 'Handling time selection event emitted from client'); + await handleWrapper(handleTimeSelection, data); +} + /** * A wrapper function for handling the keyup event. * @param keyboardInput - the keyboard input of the keyup event @@ -407,6 +417,7 @@ const registerInputHandlers = (socket: Socket) => { socket.on("input:forward", onGoForward); socket.on("input:date", onDateSelection); socket.on("input:dropdown", onDropdownSelection); + socket.on("input:time", onTimeSelection); socket.on("action", onGenerateAction); }; From 66f3ccd34fa8c06da8dd35b5277e093b318109aa Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 16:26:23 +0530 Subject: [PATCH 045/238] trigger socket event to display time picker --- src/components/atoms/canvas.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/components/atoms/canvas.tsx b/src/components/atoms/canvas.tsx index fc778963b..77128a65e 100644 --- a/src/components/atoms/canvas.tsx +++ b/src/components/atoms/canvas.tsx @@ -5,6 +5,7 @@ import { useGlobalInfoStore } from "../../context/globalInfo"; import { useActionContext } from '../../context/browserActions'; import DatePicker from './DatePicker'; import Dropdown from './Dropdown'; +import TimePicker from './TimePicker'; interface CreateRefCallback { (ref: React.RefObject): void; @@ -49,6 +50,11 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { }>; } | null>(null); + const [timePickerInfo, setTimePickerInfo] = React.useState<{ + coordinates: Coordinates; + selector: string; + } | null>(null); + const notifyLastAction = (action: string) => { if (lastAction !== action) { setLastAction(action); @@ -81,6 +87,10 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { setDropdownInfo(info); }); + socket.on('showTimePicker', (info: {coordinates: Coordinates, selector: string}) => { + setTimePickerInfo(info); + }); + return () => { socket.off('showDatePicker'); socket.off('showDropdown'); @@ -205,6 +215,13 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { onClose={() => setDropdownInfo(null)} /> )} + {timePickerInfo && ( + setTimePickerInfo(null)} + /> + )} ); From a97837d8b8cc20fcc943362d2745fff9d21c662d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Thu, 19 Dec 2024 16:26:57 +0530 Subject: [PATCH 046/238] feat: add time picker component to input time --- src/components/atoms/TimePicker.tsx | 130 ++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 src/components/atoms/TimePicker.tsx diff --git a/src/components/atoms/TimePicker.tsx b/src/components/atoms/TimePicker.tsx new file mode 100644 index 000000000..31353c7a4 --- /dev/null +++ b/src/components/atoms/TimePicker.tsx @@ -0,0 +1,130 @@ +import React, { useState } from 'react'; +import { useSocketStore } from '../../context/socket'; +import { Coordinates } from './canvas'; + +interface TimePickerProps { + coordinates: Coordinates; + selector: string; + onClose: () => void; +} + +const TimePicker = ({ coordinates, selector, onClose }: TimePickerProps) => { + const { socket } = useSocketStore(); + const [hoveredHour, setHoveredHour] = useState(null); + const [hoveredMinute, setHoveredMinute] = useState(null); + const [selectedHour, setSelectedHour] = useState(null); + const [selectedMinute, setSelectedMinute] = useState(null); + + const handleHourSelect = (hour: number) => { + setSelectedHour(hour); + // If minute is already selected, complete the selection + if (selectedMinute !== null) { + const formattedHour = hour.toString().padStart(2, '0'); + const formattedMinute = selectedMinute.toString().padStart(2, '0'); + if (socket) { + socket.emit('input:time', { + selector, + value: `${formattedHour}:${formattedMinute}` + }); + } + onClose(); + } + }; + + const handleMinuteSelect = (minute: number) => { + setSelectedMinute(minute); + // If hour is already selected, complete the selection + if (selectedHour !== null) { + const formattedHour = selectedHour.toString().padStart(2, '0'); + const formattedMinute = minute.toString().padStart(2, '0'); + if (socket) { + socket.emit('input:time', { + selector, + value: `${formattedHour}:${formattedMinute}` + }); + } + onClose(); + } + }; + + const containerStyle: React.CSSProperties = { + position: 'absolute', + left: coordinates.x, + top: coordinates.y, + zIndex: 1000, + display: 'flex', + backgroundColor: 'white', + border: '1px solid rgb(169, 169, 169)', + boxShadow: '0 2px 4px rgba(0,0,0,0.15)', + }; + + const columnStyle: React.CSSProperties = { + width: '60px', + maxHeight: '180px', + overflowY: 'auto', + overflowX: 'hidden', + borderRight: '1px solid rgb(169, 169, 169)', + }; + + const getOptionStyle = (value: number, isHour: boolean): React.CSSProperties => { + const isHovered = isHour ? hoveredHour === value : hoveredMinute === value; + const isSelected = isHour ? selectedHour === value : selectedMinute === value; + + return { + fontSize: '13.333px', + lineHeight: '18px', + padding: '0 3px', + cursor: 'default', + backgroundColor: isSelected ? '#0078D7' : isHovered ? '#0078D7' : 'white', + color: (isSelected || isHovered) ? 'white' : 'black', + userSelect: 'none', + }; + }; + + const hours = Array.from({ length: 24 }, (_, i) => i); + const minutes = Array.from({ length: 60 }, (_, i) => i); + + return ( +
+
e.stopPropagation()} + > + {/* Hours column */} +
+ {hours.map((hour) => ( +
setHoveredHour(hour)} + onMouseLeave={() => setHoveredHour(null)} + onClick={() => handleHourSelect(hour)} + > + {hour.toString().padStart(2, '0')} +
+ ))} +
+ + {/* Minutes column */} +
+ {minutes.map((minute) => ( +
setHoveredMinute(minute)} + onMouseLeave={() => setHoveredMinute(null)} + onClick={() => handleMinuteSelect(minute)} + > + {minute.toString().padStart(2, '0')} +
+ ))} +
+
+
+ ); +}; + +export default TimePicker; \ No newline at end of file From 60b901a1a06c3240040dfefcbd9f861e506d71c8 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 13:55:48 +0530 Subject: [PATCH 047/238] feat: handle select tags --- server/src/workflow-management/selector.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 9c62139bf..e1dbf4db4 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -53,7 +53,14 @@ export const getElementInformation = async ( info.url = (element as HTMLAnchorElement).href; info.innerText = element.innerText ?? ''; } else if (element?.tagName === 'IMG') { - info.imageUrl = (element as HTMLImageElement).src; + info.imageUrl = (element as HTMLImageElement).src; + } else if (element?.tagName === 'SELECT') { + const selectElement = element as HTMLSelectElement; + info.innerText = selectElement.options[selectElement.selectedIndex]?.text ?? ''; + info.attributes = { + ...info.attributes, + selectedValue: selectElement.value, + }; } else { info.hasOnlyText = element?.children?.length === 0 && element?.innerText?.length > 0; From 0ff1f4ca0736d97a4236df88d302367e114541b3 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 14:47:39 +0530 Subject: [PATCH 048/238] feat: add lang support for german --- public/locales/de.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index d12b2489a..86f1ceb2f 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -46,5 +46,15 @@ "apikey": "API-Schlüssel", "feedback": "Maxun Cloud beitreten", "apidocs": "API-Dokumentation" + }, + "runstable": { + "runs": "Alle Ausführungen", + "runStatus": "Status", + "runName": "Name", + "startedAt": "Gestartet am", + "finishedAt": "Beendet am", + "delete": "Löschen", + "settings": "Einstellungen", + "search": "Ausführungen suchen..." } } From 082df9102cd543e9785156a382a74d9b97dbd682 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 14:48:12 +0530 Subject: [PATCH 049/238] feat: add lang support for spanish --- public/locales/es.json | 70 +++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/public/locales/es.json b/public/locales/es.json index 00589622e..4e717ce2b 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -1,13 +1,61 @@ { - "app": { - "name": "Maxun", - "version": "beta" + "login": { + "title": "¡Bienvenido de nuevo!", + "email": "Correo electrónico", + "password": "Contraseña", + "button": "Iniciar sesión", + "loading": "Cargando", + "register_prompt": "¿No tienes una cuenta?", + "register_link": "Registrarse", + "welcome_notification": "¡Bienvenido a Maxun!", + "error_notification": "Error al iniciar sesión. Por favor, inténtalo de nuevo." + }, + "register": { + "title": "Crear cuenta", + "email": "Correo electrónico", + "password": "Contraseña", + "button": "Registrarse", + "loading": "Cargando", + "register_prompt": "¿Ya tienes una cuenta?", + "login_link": "Iniciar sesión", + "welcome_notification": "¡Bienvenido a Maxun!", + "error_notification": "Error en el registro. Por favor, inténtalo de nuevo." + }, + "recordingtable": { + "run": "Ejecutar", + "name": "Nombre", + "schedule": "Programar", + "integrate": "Integrar", + "settings": "Ajustes", + "options": "Opciones", + "heading": "Mis Robots", + "new": "Crear Robot", + "modal": { + "title": "Ingresa la URL", + "label": "URL", + "button": "Comenzar grabación" }, - "login": { - "title": "¡Bienvenido de nuevo!", - "email": "Correo electrónico", - "password": "Contraseña", - "button": "Iniciar sesión", - "register_prompt": "¿No tienes una cuenta? Regístrate" - } - } \ No newline at end of file + "edit": "Editar", + "delete": "Eliminar", + "duplicate": "Duplicar", + "search": "Buscar robots..." + }, + "mainmenu": { + "recordings": "Robots", + "runs": "Ejecuciones", + "proxy": "Proxy", + "apikey": "Clave API", + "feedback": "Unirse a Maxun Cloud", + "apidocs": "Documentación API" + }, + "runstable": { + "runs": "Todas las ejecuciones", + "runStatus": "Estado", + "runName": "Nombre", + "startedAt": "Iniciado el", + "finishedAt": "Finalizado el", + "delete": "Eliminar", + "settings": "Ajustes", + "search": "Buscar ejecuciones..." + } +} \ No newline at end of file From 65266c2af659346ca5bd63e87d0b2e12cd568b1a Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 14:48:33 +0530 Subject: [PATCH 050/238] feat: add lang support for chinese --- public/locales/zh.json | 70 +++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 11 deletions(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index 7fa8bb608..31bce4944 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -1,13 +1,61 @@ { - "app": { - "name": "Maxun", - "version": "beta" + "login": { + "title": "欢迎回来!", + "email": "电子邮箱", + "password": "密码", + "button": "登录", + "loading": "加载中", + "register_prompt": "还没有账号?", + "register_link": "注册", + "welcome_notification": "欢迎使用 Maxun!", + "error_notification": "登录失败。请重试。" + }, + "register": { + "title": "注册账号", + "email": "电子邮箱", + "password": "密码", + "button": "注册", + "loading": "加载中", + "register_prompt": "已有账号?", + "login_link": "登录", + "welcome_notification": "欢迎使用 Maxun!", + "error_notification": "注册失败。请重试。" + }, + "recordingtable": { + "run": "运行", + "name": "名称", + "schedule": "计划", + "integrate": "集成", + "settings": "设置", + "options": "选项", + "heading": "我的机器人", + "new": "创建机器人", + "modal": { + "title": "输入URL", + "label": "URL", + "button": "开始录制" }, - "login": { - "title": "欢迎回来!", - "email": "电子邮件", - "password": "密码", - "button": "登录", - "register_prompt": "没有账号?注册" - } - } \ No newline at end of file + "edit": "编辑", + "delete": "删除", + "duplicate": "复制", + "search": "搜索机器人..." + }, + "mainmenu": { + "recordings": "机器人", + "runs": "运行记录", + "proxy": "代理", + "apikey": "API密钥", + "feedback": "加入 Maxun Cloud", + "apidocs": "API文档" + }, + "runstable": { + "runs": "所有运行记录", + "runStatus": "状态", + "runName": "名称", + "startedAt": "开始时间", + "finishedAt": "结束时间", + "delete": "删除", + "settings": "设置", + "search": "搜索运行记录..." + } +} \ No newline at end of file From 39850df42e096e10dffdf0b4b6acfe4c91c0f40f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 14:49:50 +0530 Subject: [PATCH 051/238] feat: rm arabic lang option --- src/components/molecules/NavBar.tsx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index ead395c54..0658a7668 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -296,14 +296,14 @@ export const NavBar: React.FC = ({ > 日本語 - { changeLanguage("ar"); handleMenuClose(); }} > العربية - + */} { changeLanguage("zh"); @@ -318,8 +318,7 @@ export const NavBar: React.FC = ({ handleMenuClose(); }} > - German - + Deutsch @@ -373,14 +372,14 @@ export const NavBar: React.FC = ({ > 日本語 - { changeLanguage("ar"); handleMenuClose(); }} > العربية - + */} { changeLanguage("zh"); @@ -389,6 +388,14 @@ export const NavBar: React.FC = ({ > 中文 + { + changeLanguage("de"); + handleMenuClose(); + }} + > + Deutsch + )} From 7860d404449f88b9c503cdd9b96433789bd167c9 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:17:49 +0530 Subject: [PATCH 052/238] feat: handle input type time --- server/src/workflow-management/selector.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index e1dbf4db4..0d17c9b45 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -61,6 +61,8 @@ export const getElementInformation = async ( ...info.attributes, selectedValue: selectElement.value, }; + } else if (element?.tagName === 'INPUT' && element?.type === 'time') { + info.innerText = element.value; } else { info.hasOnlyText = element?.children?.length === 0 && element?.innerText?.length > 0; From 4b2c0721392e1679a56e66c8b2e33111bc792e24 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:18:06 +0530 Subject: [PATCH 053/238] feat: assign proper types --- server/src/workflow-management/selector.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 0d17c9b45..f1259abc4 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -61,8 +61,8 @@ export const getElementInformation = async ( ...info.attributes, selectedValue: selectElement.value, }; - } else if (element?.tagName === 'INPUT' && element?.type === 'time') { - info.innerText = element.value; + } else if (element?.tagName === 'INPUT' && (element as HTMLInputElement).type === 'time') { + info.innerText = (element as HTMLInputElement).value; } else { info.hasOnlyText = element?.children?.length === 0 && element?.innerText?.length > 0; From 81eb32254c1cdea4f977f36bf362959d6ff611f1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:23:44 +0530 Subject: [PATCH 054/238] feat: handle input type date --- server/src/workflow-management/selector.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index f1259abc4..6770c18b7 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -61,7 +61,7 @@ export const getElementInformation = async ( ...info.attributes, selectedValue: selectElement.value, }; - } else if (element?.tagName === 'INPUT' && (element as HTMLInputElement).type === 'time') { + } else if (element?.tagName === 'INPUT' && (element as HTMLInputElement).type === 'time' || (element as HTMLInputElement).type === 'date') { info.innerText = (element as HTMLInputElement).value; } else { info.hasOnlyText = element?.children?.length === 0 && From 889107d892dad91d705746d22e425674989f5541 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:23:59 +0530 Subject: [PATCH 055/238] chore: lint --- server/src/workflow-management/selector.ts | 166 ++++++++++----------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/server/src/workflow-management/selector.ts b/server/src/workflow-management/selector.ts index 6770c18b7..240f8921b 100644 --- a/server/src/workflow-management/selector.ts +++ b/server/src/workflow-management/selector.ts @@ -53,16 +53,16 @@ export const getElementInformation = async ( info.url = (element as HTMLAnchorElement).href; info.innerText = element.innerText ?? ''; } else if (element?.tagName === 'IMG') { - info.imageUrl = (element as HTMLImageElement).src; - } else if (element?.tagName === 'SELECT') { - const selectElement = element as HTMLSelectElement; - info.innerText = selectElement.options[selectElement.selectedIndex]?.text ?? ''; - info.attributes = { + info.imageUrl = (element as HTMLImageElement).src; + } else if (element?.tagName === 'SELECT') { + const selectElement = element as HTMLSelectElement; + info.innerText = selectElement.options[selectElement.selectedIndex]?.text ?? ''; + info.attributes = { ...info.attributes, selectedValue: selectElement.value, - }; + }; } else if (element?.tagName === 'INPUT' && (element as HTMLInputElement).type === 'time' || (element as HTMLInputElement).type === 'date') { - info.innerText = (element as HTMLInputElement).value; + info.innerText = (element as HTMLInputElement).value; } else { info.hasOnlyText = element?.children?.length === 0 && element?.innerText?.length > 0; @@ -865,118 +865,118 @@ export const getNonUniqueSelectors = async (page: Page, coordinates: Coordinates try { if (!listSelector) { console.log(`NON UNIQUE: MODE 1`) - const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { - function getNonUniqueSelector(element: HTMLElement): string { - let selector = element.tagName.toLowerCase(); - - if (element.className) { - const classes = element.className.split(/\s+/).filter((cls: string) => Boolean(cls)); - if (classes.length > 0) { - const validClasses = classes.filter((cls: string) => !cls.startsWith('!') && !cls.includes(':')); - if (validClasses.length > 0) { - selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.'); + const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { + function getNonUniqueSelector(element: HTMLElement): string { + let selector = element.tagName.toLowerCase(); + + if (element.className) { + const classes = element.className.split(/\s+/).filter((cls: string) => Boolean(cls)); + if (classes.length > 0) { + const validClasses = classes.filter((cls: string) => !cls.startsWith('!') && !cls.includes(':')); + if (validClasses.length > 0) { + selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.'); + } } } + + return selector; } - return selector; - } + function getSelectorPath(element: HTMLElement | null): string { + const path: string[] = []; + let depth = 0; + const maxDepth = 2; - function getSelectorPath(element: HTMLElement | null): string { - const path: string[] = []; - let depth = 0; - const maxDepth = 2; - - while (element && element !== document.body && depth < maxDepth) { - const selector = getNonUniqueSelector(element); - path.unshift(selector); - element = element.parentElement; - depth++; - } + while (element && element !== document.body && depth < maxDepth) { + const selector = getNonUniqueSelector(element); + path.unshift(selector); + element = element.parentElement; + depth++; + } - return path.join(' > '); - } + return path.join(' > '); + } - const originalEl = document.elementFromPoint(x, y) as HTMLElement; - if (!originalEl) return null; + const originalEl = document.elementFromPoint(x, y) as HTMLElement; + if (!originalEl) return null; - let element = originalEl; + let element = originalEl; - // if (listSelector === '') { + // if (listSelector === '') { while (element.parentElement) { const parentRect = element.parentElement.getBoundingClientRect(); const childRect = element.getBoundingClientRect(); - + const fullyContained = parentRect.left <= childRect.left && parentRect.right >= childRect.right && parentRect.top <= childRect.top && parentRect.bottom >= childRect.bottom; - + const significantOverlap = (childRect.width * childRect.height) / (parentRect.width * parentRect.height) > 0.5; - + if (fullyContained && significantOverlap) { element = element.parentElement; } else { break; } } - // } - - const generalSelector = getSelectorPath(element); - return { - generalSelector, - }; - }, coordinates); - return selectors || { generalSelector: '' }; - } else { - console.log(`NON UNIQUE: MODE 2`) - const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { - function getNonUniqueSelector(element: HTMLElement): string { - let selector = element.tagName.toLowerCase(); + // } - if (element.className) { - const classes = element.className.split(/\s+/).filter((cls: string) => Boolean(cls)); - if (classes.length > 0) { - const validClasses = classes.filter((cls: string) => !cls.startsWith('!') && !cls.includes(':')); - if (validClasses.length > 0) { - selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.'); + const generalSelector = getSelectorPath(element); + return { + generalSelector, + }; + }, coordinates); + return selectors || { generalSelector: '' }; + } else { + console.log(`NON UNIQUE: MODE 2`) + const selectors = await page.evaluate(({ x, y }: { x: number, y: number }) => { + function getNonUniqueSelector(element: HTMLElement): string { + let selector = element.tagName.toLowerCase(); + + if (element.className) { + const classes = element.className.split(/\s+/).filter((cls: string) => Boolean(cls)); + if (classes.length > 0) { + const validClasses = classes.filter((cls: string) => !cls.startsWith('!') && !cls.includes(':')); + if (validClasses.length > 0) { + selector += '.' + validClasses.map(cls => CSS.escape(cls)).join('.'); + } } } + + return selector; } - return selector; - } + function getSelectorPath(element: HTMLElement | null): string { + const path: string[] = []; + let depth = 0; + const maxDepth = 2; - function getSelectorPath(element: HTMLElement | null): string { - const path: string[] = []; - let depth = 0; - const maxDepth = 2; - - while (element && element !== document.body && depth < maxDepth) { - const selector = getNonUniqueSelector(element); - path.unshift(selector); - element = element.parentElement; - depth++; - } + while (element && element !== document.body && depth < maxDepth) { + const selector = getNonUniqueSelector(element); + path.unshift(selector); + element = element.parentElement; + depth++; + } - return path.join(' > '); - } + return path.join(' > '); + } - const originalEl = document.elementFromPoint(x, y) as HTMLElement; - if (!originalEl) return null; + const originalEl = document.elementFromPoint(x, y) as HTMLElement; + if (!originalEl) return null; - let element = originalEl; + let element = originalEl; - const generalSelector = getSelectorPath(element); - return { - generalSelector, - }; - }, coordinates); - return selectors || { generalSelector: '' }; - } + const generalSelector = getSelectorPath(element); + return { + generalSelector, + }; + }, coordinates); + return selectors || { generalSelector: '' }; + } } catch (error) { console.error('Error in getNonUniqueSelectors:', error); From a1f31ec05d00dbac4dcd12759d66005e3832031d Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:44:10 +0530 Subject: [PATCH 056/238] feat: local setup upgrade cd step --- src/components/molecules/NavBar.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index c2f271cf9..54805ef7d 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -25,7 +25,7 @@ export const NavBar: React.FC = ({ recordingName, isRecording }) => const navigate = useNavigate(); const [anchorEl, setAnchorEl] = useState(null); - const currentVersion = packageJson.version; + const currentVersion = "0.0.3" const [open, setOpen] = useState(false); const [latestVersion, setLatestVersion] = useState(null); @@ -208,6 +208,11 @@ export const NavBar: React.FC = ({ recordingName, isRecording }) =>

Run the commands below

+ # cd to project directory (eg: maxun) +
+ cd maxun +
+
# pull latest changes
git pull origin master From b6274cca14b878c9d0c00ef283c1d8ef00c381ec Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:44:39 +0530 Subject: [PATCH 057/238] feat: docker setup upgrade cd step --- src/components/molecules/NavBar.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 54805ef7d..0816b0e87 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -233,6 +233,11 @@ export const NavBar: React.FC = ({ recordingName, isRecording }) =>

Run the commands below

+ # cd to project directory (eg: maxun) +
+ cd maxun +
+
# pull latest docker images
docker-compose pull From 5b3b6d848f9ce33df328cd46bf4b2cb9a9684fcb Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:45:49 +0530 Subject: [PATCH 058/238] feat: docker setup container down --- src/components/molecules/NavBar.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 0816b0e87..9acfe57b2 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -238,6 +238,11 @@ export const NavBar: React.FC = ({ recordingName, isRecording }) => cd maxun

+ # stop the working containers +
+ docker-compose down +
+
# pull latest docker images
docker-compose pull From 6da2f6a130a562c5abf42785a9157161b8fc05d6 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 17:47:28 +0530 Subject: [PATCH 059/238] feat: revert to version --- src/components/molecules/NavBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 9acfe57b2..24c41b202 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -25,7 +25,7 @@ export const NavBar: React.FC = ({ recordingName, isRecording }) => const navigate = useNavigate(); const [anchorEl, setAnchorEl] = useState(null); - const currentVersion = "0.0.3" + const currentVersion = packageJson.version; const [open, setOpen] = useState(false); const [latestVersion, setLatestVersion] = useState(null); From 2b96f07b36cd4f1a8ac35a54f49915f669b01220 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 19:52:03 +0530 Subject: [PATCH 060/238] feat: add datetime-local selection pair to workflow --- .../workflow-management/classes/Generator.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 9ff4922e5..609541de1 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -315,6 +315,26 @@ export class WorkflowGenerator { await this.addPairToWorkflowAndNotifyClient(pair, page); }; + public onDateTimeLocalSelection = async (page: Page, data: { selector: string, value: string }) => { + const { selector, value } = data; + + try { + await page.fill(selector, value); + } catch (error) { + console.error("Failed to fill datetime-local value:", error); + } + + const pair: WhereWhatPair = { + where: { url: this.getBestUrl(page.url()) }, + what: [{ + action: 'fill', + args: [selector, value], + }], + }; + + await this.addPairToWorkflowAndNotifyClient(pair, page); + }; + /** * Generates a pair for the click event. * @param coordinates The coordinates of the click event. @@ -390,6 +410,16 @@ export class WorkflowGenerator { return; } + const isDateTimeLocal = elementInfo?.tagName === 'INPUT' && elementInfo?.attributes?.type === 'datetime-local'; + + if (isDateTimeLocal) { + this.socket.emit('showDateTimePicker', { + coordinates, + selector + }); + return; + } + //const element = await getElementMouseIsOver(page, coordinates); //logger.log('debug', `Element: ${JSON.stringify(element, null, 2)}`); if (selector) { From 6d792f365ec5526431d13b08030c315ff5f6f623 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 19:52:55 +0530 Subject: [PATCH 061/238] feat: add datetime-local selection event handlers --- server/src/browser-management/inputHandlers.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/server/src/browser-management/inputHandlers.ts b/server/src/browser-management/inputHandlers.ts index 982e18de8..bf365053f 100644 --- a/server/src/browser-management/inputHandlers.ts +++ b/server/src/browser-management/inputHandlers.ts @@ -260,6 +260,16 @@ const onTimeSelection = async (data: { selector: string, value: string }) => { await handleWrapper(handleTimeSelection, data); } +const handleDateTimeLocalSelection = async (generator: WorkflowGenerator, page: Page, data: { selector: string, value: string }) => { + await generator.onDateTimeLocalSelection(page, data); + logger.log('debug', `DateTime Local value ${data.value} selected`); +} + +const onDateTimeLocalSelection = async (data: { selector: string, value: string }) => { + logger.log('debug', 'Handling datetime-local selection event emitted from client'); + await handleWrapper(handleDateTimeLocalSelection, data); +} + /** * A wrapper function for handling the keyup event. * @param keyboardInput - the keyboard input of the keyup event @@ -418,6 +428,7 @@ const registerInputHandlers = (socket: Socket) => { socket.on("input:date", onDateSelection); socket.on("input:dropdown", onDropdownSelection); socket.on("input:time", onTimeSelection); + socket.on("input:datetime-local", onDateTimeLocalSelection); socket.on("action", onGenerateAction); }; From b1fbcb506c87783e8a953943df37dc2b56080ae5 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 19:54:05 +0530 Subject: [PATCH 062/238] feat: trigger socket event to display datime-local picker --- src/components/atoms/canvas.tsx | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/components/atoms/canvas.tsx b/src/components/atoms/canvas.tsx index 77128a65e..e71a4d937 100644 --- a/src/components/atoms/canvas.tsx +++ b/src/components/atoms/canvas.tsx @@ -6,6 +6,7 @@ import { useActionContext } from '../../context/browserActions'; import DatePicker from './DatePicker'; import Dropdown from './Dropdown'; import TimePicker from './TimePicker'; +import DateTimeLocalPicker from './DateTimeLocalPicker'; interface CreateRefCallback { (ref: React.RefObject): void; @@ -55,6 +56,11 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { selector: string; } | null>(null); + const [dateTimeLocalInfo, setDateTimeLocalInfo] = React.useState<{ + coordinates: Coordinates; + selector: string; + } | null>(null); + const notifyLastAction = (action: string) => { if (lastAction !== action) { setLastAction(action); @@ -91,9 +97,15 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { setTimePickerInfo(info); }); + socket.on('showDateTimePicker', (info: {coordinates: Coordinates, selector: string}) => { + setDateTimeLocalInfo(info); + }); + return () => { socket.off('showDatePicker'); socket.off('showDropdown'); + socket.off('showTimePicker'); + socket.off('showDateTimePicker'); }; } }, [socket]); @@ -222,6 +234,13 @@ const Canvas = ({ width, height, onCreateRef }: CanvasProps) => { onClose={() => setTimePickerInfo(null)} /> )} + {dateTimeLocalInfo && ( + setDateTimeLocalInfo(null)} + /> + )} ); From 15aa85976abd4f3f07f62c6f66b95087f047e31b Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 19:55:17 +0530 Subject: [PATCH 063/238] feat: add dateime-local picker component --- src/components/atoms/DateTimeLocalPicker.tsx | 74 ++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/components/atoms/DateTimeLocalPicker.tsx diff --git a/src/components/atoms/DateTimeLocalPicker.tsx b/src/components/atoms/DateTimeLocalPicker.tsx new file mode 100644 index 000000000..dc62a79b9 --- /dev/null +++ b/src/components/atoms/DateTimeLocalPicker.tsx @@ -0,0 +1,74 @@ +import React, { useState } from 'react'; +import { useSocketStore } from '../../context/socket'; +import { Coordinates } from './canvas'; + +interface DateTimeLocalPickerProps { + coordinates: Coordinates; + selector: string; + onClose: () => void; +} + +const DateTimeLocalPicker: React.FC = ({ coordinates, selector, onClose }) => { + const { socket } = useSocketStore(); + const [selectedDateTime, setSelectedDateTime] = useState(''); + + const handleDateTimeChange = (e: React.ChangeEvent) => { + setSelectedDateTime(e.target.value); + }; + + const handleConfirm = () => { + if (socket && selectedDateTime) { + socket.emit('input:datetime-local', { + selector, + value: selectedDateTime + }); + onClose(); + } + }; + + return ( +
+
+ +
+ + +
+
+
+ ); +}; + +export default DateTimeLocalPicker; \ No newline at end of file From 5df00b59304d986687f7b04d2da5703c6dafcaf6 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:02:01 +0530 Subject: [PATCH 064/238] feat: add german translation for proxy page --- public/locales/de.json | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 86f1ceb2f..ef0cc31a1 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -56,5 +56,41 @@ "delete": "Löschen", "settings": "Einstellungen", "search": "Ausführungen suchen..." + }, + "proxy": { + "title": "Proxy-Konfiguration", + "tab_standard": "Standard-Proxy", + "tab_rotation": "Automatische Proxy-Rotation", + "server_url": "Proxy-Server-URL", + "server_url_helper": "Proxy für alle Roboter. HTTP- und SOCKS-Proxys werden unterstützt. Beispiel http://myproxy.com:3128 oder socks5://myproxy.com:3128. Kurzform myproxy.com:3128 wird als HTTP-Proxy behandelt.", + "requires_auth": "Authentifizierung erforderlich?", + "username": "Benutzername", + "password": "Passwort", + "add_proxy": "Proxy hinzufügen", + "test_proxy": "Proxy testen", + "remove_proxy": "Proxy entfernen", + "table": { + "proxy_url": "Proxy-URL", + "requires_auth": "Authentifizierung erforderlich" + }, + "coming_soon": "Demnächst verfügbar - In Open Source (Basis-Rotation) & Cloud (Erweiterte Rotation). Wenn Sie die Infrastruktur nicht selbst verwalten möchten, tragen Sie sich in unsere Cloud-Warteliste ein.", + "join_waitlist": "Maxun Cloud Warteliste beitreten", + "alert": { + "title": "Wenn Ihr Proxy einen Benutzernamen und ein Passwort erfordert, geben Sie diese immer separat von der Proxy-URL an.", + "right_way": "Der richtige Weg", + "wrong_way": "Der falsche Weg", + "proxy_url": "Proxy-URL:", + "username": "Benutzername:", + "password": "Passwort:" + }, + "notifications": { + "config_success": "Proxy-Konfiguration erfolgreich übermittelt", + "config_error": "Fehler beim Übermitteln der Proxy-Konfiguration. Bitte erneut versuchen.", + "test_success": "Proxy-Konfiguration funktioniert", + "test_error": "Fehler beim Testen der Proxy-Konfiguration. Bitte erneut versuchen.", + "fetch_success": "Proxy-Konfiguration erfolgreich abgerufen", + "remove_success": "Proxy-Konfiguration erfolgreich entfernt", + "remove_error": "Fehler beim Entfernen der Proxy-Konfiguration. Bitte erneut versuchen." + } } } From 6e8815b8fd986afdecee215f8f9bf35629933633 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:02:46 +0530 Subject: [PATCH 065/238] feat: add english translation for proxy page --- public/locales/en.json | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index b6396893b..ed5582bfe 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -59,8 +59,41 @@ "delete":"Delete", "settings":"Settings", "search":"Search Runs..." - - - + }, + "proxy": { + "title": "Proxy Configuration", + "tab_standard": "Standard Proxy", + "tab_rotation": "Automatic Proxy Rotation", + "server_url": "Proxy Server URL", + "server_url_helper": "Proxy to be used for all robots. HTTP and SOCKS proxies are supported. Example http://myproxy.com:3128 or socks5://myproxy.com:3128. Short form myproxy.com:3128 is considered an HTTP proxy.", + "requires_auth": "Requires Authentication?", + "username": "Username", + "password": "Password", + "add_proxy": "Add Proxy", + "test_proxy": "Test Proxy", + "remove_proxy": "Remove Proxy", + "table": { + "proxy_url": "Proxy URL", + "requires_auth": "Requires Authentication" + }, + "coming_soon": "Coming Soon - In Open Source (Basic Rotation) & Cloud (Advanced Rotation). If you don't want to manage the infrastructure, join our cloud waitlist to get early access.", + "join_waitlist": "Join Maxun Cloud Waitlist", + "alert": { + "title": "If your proxy requires a username and password, always provide them separately from the proxy URL.", + "right_way": "The right way", + "wrong_way": "The wrong way", + "proxy_url": "Proxy URL:", + "username": "Username:", + "password": "Password:" + }, + "notifications": { + "config_success": "Proxy configuration submitted successfully", + "config_error": "Failed to submit proxy configuration. Try again.", + "test_success": "Proxy configuration is working", + "test_error": "Failed to test proxy configuration. Try again.", + "fetch_success": "Proxy configuration fetched successfully", + "remove_success": "Proxy configuration removed successfully", + "remove_error": "Failed to remove proxy configuration. Try again." + } } } \ No newline at end of file From ae037b807ade675b042d9a46625c8eca31440315 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:03:05 +0530 Subject: [PATCH 066/238] feat: add spanish translation for proxy page --- public/locales/es.json | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 4e717ce2b..bc62d2a7d 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -57,5 +57,41 @@ "delete": "Eliminar", "settings": "Ajustes", "search": "Buscar ejecuciones..." + }, + "proxy": { + "title": "Configuración del Proxy", + "tab_standard": "Proxy Estándar", + "tab_rotation": "Rotación Automática de Proxy", + "server_url": "URL del Servidor Proxy", + "server_url_helper": "Proxy para usar en todos los robots. Se admiten proxies HTTP y SOCKS. Ejemplo http://myproxy.com:3128 o socks5://myproxy.com:3128. La forma corta myproxy.com:3128 se considera un proxy HTTP.", + "requires_auth": "¿Requiere Autenticación?", + "username": "Usuario", + "password": "Contraseña", + "add_proxy": "Agregar Proxy", + "test_proxy": "Probar Proxy", + "remove_proxy": "Eliminar Proxy", + "table": { + "proxy_url": "URL del Proxy", + "requires_auth": "Requiere Autenticación" + }, + "coming_soon": "Próximamente - En Open Source (Rotación Básica) y Cloud (Rotación Avanzada). Si no desea administrar la infraestructura, únase a nuestra lista de espera en la nube para obtener acceso anticipado.", + "join_waitlist": "Unirse a la Lista de Espera de Maxun Cloud", + "alert": { + "title": "Si su proxy requiere un nombre de usuario y contraseña, proporcione siempre estos datos por separado de la URL del proxy.", + "right_way": "La forma correcta", + "wrong_way": "La forma incorrecta", + "proxy_url": "URL del Proxy:", + "username": "Usuario:", + "password": "Contraseña:" + }, + "notifications": { + "config_success": "Configuración del proxy enviada con éxito", + "config_error": "Error al enviar la configuración del proxy. Inténtelo de nuevo.", + "test_success": "La configuración del proxy funciona correctamente", + "test_error": "Error al probar la configuración del proxy. Inténtelo de nuevo.", + "fetch_success": "Configuración del proxy recuperada con éxito", + "remove_success": "Configuración del proxy eliminada con éxito", + "remove_error": "Error al eliminar la configuración del proxy. Inténtelo de nuevo." + } } } \ No newline at end of file From 9f06d437403fcd844c4e284afee7ff4e513724d4 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:03:22 +0530 Subject: [PATCH 067/238] feat: add japanese translation for proxy page --- public/locales/ja.json | 136 ++++++++++++++++++++++++++--------------- 1 file changed, 86 insertions(+), 50 deletions(-) diff --git a/public/locales/ja.json b/public/locales/ja.json index 881fd1318..2d7adc25c 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -1,61 +1,97 @@ { "login": { - "title": "お帰りなさい!", - "email": "メールアドレス", - "password": "パスワード", - "button": "ログイン", - "loading": "読み込み中", - "register_prompt": "アカウントをお持ちでないですか?", - "register_link": "登録する", - "welcome_notification": "Maxunへようこそ!", - "error_notification": "ログインに失敗しました。もう一度お試しください。" + "title": "お帰りなさい!", + "email": "メールアドレス", + "password": "パスワード", + "button": "ログイン", + "loading": "読み込み中", + "register_prompt": "アカウントをお持ちでないですか?", + "register_link": "登録する", + "welcome_notification": "Maxunへようこそ!", + "error_notification": "ログインに失敗しました。もう一度お試しください。" }, "register": { - "title": "アカウントを登録する", - "email": "メールアドレス", - "password": "パスワード", - "button": "登録する", - "loading": "読み込み中", - "register_prompt": "既にアカウントをお持ちですか?", - "login_link": "ログイン", - "welcome_notification": "Maxunへようこそ!", - "error_notification": "登録に失敗しました。もう一度お試しください。" + "title": "アカウントを登録する", + "email": "メールアドレス", + "password": "パスワード", + "button": "登録する", + "loading": "読み込み中", + "register_prompt": "既にアカウントをお持ちですか?", + "login_link": "ログイン", + "welcome_notification": "Maxunへようこそ!", + "error_notification": "登録に失敗しました。もう一度お試しください。" }, "recordingtable": { - "run": "実行", - "name": "名前", - "schedule": "スケジュール", - "integrate": "統合", - "settings": "設定", - "options": "オプション", - "heading": "私のロボット", - "new": "ロボットを作成", - "modal": { - "title": "URLを入力してください", - "label": "URL", - "button": "録画を開始" - }, - "edit": "編集", - "delete": "削除", - "duplicate": "複製", - "search": "ロボットを検索..." + "run": "実行", + "name": "名前", + "schedule": "スケジュール", + "integrate": "統合", + "settings": "設定", + "options": "オプション", + "heading": "私のロボット", + "new": "ロボットを作成", + "modal": { + "title": "URLを入力してください", + "label": "URL", + "button": "録画を開始" + }, + "edit": "編集", + "delete": "削除", + "duplicate": "複製", + "search": "ロボットを検索..." }, "mainmenu": { - "recordings": "ロボット", - "runs": "実行", - "proxy": "プロキシ", - "apikey": "APIキー", - "feedback": "Maxunクラウドに参加する", - "apidocs": "APIドキュメント" + "recordings": "ロボット", + "runs": "実行", + "proxy": "プロキシ", + "apikey": "APIキー", + "feedback": "Maxunクラウドに参加する", + "apidocs": "APIドキュメント" }, "runstable": { - "runs": "すべての実行", - "runStatus": "ステータス", - "runName": "名前", - "startedAt": "開始日時", - "finishedAt": "終了日時", - "delete": "削除", - "settings": "設定", - "search": "実行を検索..." - } + "runs": "すべての実行", + "runStatus": "ステータス", + "runName": "名前", + "startedAt": "開始日時", + "finishedAt": "終了日時", + "delete": "削除", + "settings": "設定", + "search": "実行を検索..." + }, + "proxy": { + "title": "プロキシ設定", + "tab_standard": "標準プロキシ", + "tab_rotation": "自動プロキシローテーション", + "server_url": "プロキシサーバーURL", + "server_url_helper": "すべてのロボットで使用するプロキシ。HTTPとSOCKSプロキシがサポートされています。例:http://myproxy.com:3128 または socks5://myproxy.com:3128。短縮形 myproxy.com:3128 はHTTPプロキシとして扱われます。", + "requires_auth": "認証が必要ですか?", + "username": "ユーザー名", + "password": "パスワード", + "add_proxy": "プロキシを追加", + "test_proxy": "プロキシをテスト", + "remove_proxy": "プロキシを削除", + "table": { + "proxy_url": "プロキシURL", + "requires_auth": "認証が必要" + }, + "coming_soon": "近日公開 - オープンソース(基本ローテーション)とクラウド(高度なローテーション)。インフラストラクチャを管理したくない場合は、クラウドの待機リストに参加して早期アクセスを取得してください。", + "join_waitlist": "Maxun Cloud待機リストに参加", + "alert": { + "title": "プロキシにユーザー名とパスワードが必要な場合は、必ずプロキシURLとは別に指定してください。", + "right_way": "正しい方法", + "wrong_way": "間違った方法", + "proxy_url": "プロキシURL:", + "username": "ユーザー名:", + "password": "パスワード:" + }, + "notifications": { + "config_success": "プロキシ設定が正常に送信されました", + "config_error": "プロキシ設定の送信に失敗しました。もう一度お試しください。", + "test_success": "プロキシ設定は正常に動作しています", + "test_error": "プロキシ設定のテストに失敗しました。もう一度お試しください。", + "fetch_success": "プロキシ設定の取得に成功しました", + "remove_success": "プロキシ設定が正常に削除されました", + "remove_error": "プロキシ設定の削除に失敗しました。もう一度お試しください。" + } + } } From 18f7d75ef3ac6817360e996d5bca47b7139950af Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:03:36 +0530 Subject: [PATCH 068/238] feat: add chinese translation for proxy page --- public/locales/zh.json | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 31bce4944..52b2ce3ef 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -57,5 +57,41 @@ "delete": "删除", "settings": "设置", "search": "搜索运行记录..." + }, + "proxy": { + "title": "代理设置", + "tab_standard": "标准代理", + "tab_rotation": "自动代理轮换", + "server_url": "代理服务器URL", + "server_url_helper": "用于所有机器人的代理。支持HTTP和SOCKS代理。示例 http://myproxy.com:3128 或 socks5://myproxy.com:3128。简短形式 myproxy.com:3128 被视为HTTP代理。", + "requires_auth": "需要认证?", + "username": "用户名", + "password": "密码", + "add_proxy": "添加代理", + "test_proxy": "测试代理", + "remove_proxy": "删除代理", + "table": { + "proxy_url": "代理URL", + "requires_auth": "需要认证" + }, + "coming_soon": "即将推出 - 开源版(基础轮换)和云版(高级轮换)。如果您不想管理基础设施,请加入我们的云服务等候名单以获得早期访问权限。", + "join_waitlist": "加入Maxun Cloud等候名单", + "alert": { + "title": "如果您的代理需要用户名和密码,请务必将它们与代理URL分开提供。", + "right_way": "正确方式", + "wrong_way": "错误方式", + "proxy_url": "代理URL:", + "username": "用户名:", + "password": "密码:" + }, + "notifications": { + "config_success": "代理配置提交成功", + "config_error": "提交代理配置失败。请重试。", + "test_success": "代理配置运行正常", + "test_error": "测试代理配置失败。请重试。", + "fetch_success": "成功获取代理配置", + "remove_success": "成功删除代理配置", + "remove_error": "删除代理配置失败。请重试。" + } } } \ No newline at end of file From e404b74d2c37dff7084a59a9f25a7d29107fc2a2 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:04:44 +0530 Subject: [PATCH 069/238] feat: add translation for proxy page --- src/components/organisms/ProxyForm.tsx | 64 +++++++++++++------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/components/organisms/ProxyForm.tsx b/src/components/organisms/ProxyForm.tsx index a581144ba..8fbf730af 100644 --- a/src/components/organisms/ProxyForm.tsx +++ b/src/components/organisms/ProxyForm.tsx @@ -3,6 +3,7 @@ import { styled } from '@mui/system'; import { Alert, AlertTitle, TextField, Button, Switch, FormControlLabel, Box, Typography, Tabs, Tab, Table, TableContainer, TableHead, TableRow, TableBody, TableCell, Paper } from '@mui/material'; import { sendProxyConfig, getProxyConfig, testProxyConfig, deleteProxyConfig } from '../../api/proxy'; import { useGlobalInfoStore } from '../../context/globalInfo'; +import { useTranslation } from 'react-i18next'; const FormContainer = styled(Box)({ display: 'flex', @@ -16,6 +17,7 @@ const FormControl = styled(Box)({ }); const ProxyForm: React.FC = () => { + const { t } = useTranslation(); const [proxyConfigForm, setProxyConfigForm] = useState({ server_url: '', username: '', @@ -79,9 +81,9 @@ const ProxyForm: React.FC = () => { try { const response = await sendProxyConfig(proxyConfigForm); if (response) { - notify('success', 'Proxy configuration submitted successfully'); + notify('success', t('proxy.notifications.config_success')); } else { - notify('error', `Failed to submit proxy configuration. Try again. ${response}`); + notify('error', t('proxy.notifications.config_error')); console.log(`Failed to submit proxy configuration. Try again. ${response}`) } } catch (error: any) { @@ -96,9 +98,9 @@ const ProxyForm: React.FC = () => { const testProxy = async () => { await testProxyConfig().then((response) => { if (response.success) { - notify('success', 'Proxy configuration is working'); + notify('success', t('proxy.notifications.test_success')); } else { - notify('error', 'Failed to test proxy configuration. Try again.'); + notify('error', t('proxy.notifications.test_error')); } }); }; @@ -109,7 +111,7 @@ const ProxyForm: React.FC = () => { if (response.proxy_url) { setIsProxyConfigured(true); setProxy(response); - notify('success', 'Proxy configuration fetched successfully'); + notify('success', t('proxy.notifications.fetch_success')); } } catch (error: any) { notify('error', error); @@ -119,11 +121,11 @@ const ProxyForm: React.FC = () => { const removeProxy = async () => { await deleteProxyConfig().then((response) => { if (response) { - notify('success', 'Proxy configuration removed successfully'); + notify('success', t('proxy.notifications.remove_success')); setIsProxyConfigured(false); setProxy({ proxy_url: '', auth: false }); } else { - notify('error', 'Failed to remove proxy configuration. Try again.'); + notify('error', t('proxy.notifications.remove_error')); } }); } @@ -136,11 +138,11 @@ const ProxyForm: React.FC = () => { <> - Proxy Configuration + {t('proxy.title')} - - + + {tabIndex === 0 && ( isProxyConfigured ? ( @@ -149,8 +151,8 @@ const ProxyForm: React.FC = () => {
- Proxy URL - Requires Authentication + {t('proxy.table.proxy_url')} + {t('proxy.table.requires_auth')} @@ -162,39 +164,37 @@ const ProxyForm: React.FC = () => {
) : ( } - label="Requires Authentication?" + label={t('proxy.requires_auth')} /> {requiresAuth && ( <> { { fullWidth disabled={!proxyConfigForm.server_url || (requiresAuth && (!proxyConfigForm.username || !proxyConfigForm.password))} > - Add Proxy + {t('proxy.add_proxy')} ))} @@ -234,33 +234,33 @@ const ProxyForm: React.FC = () => { <> - Coming Soon - In Open Source (Basic Rotation) & Cloud (Advanced Rotation). If you don't want to manage the infrastructure, join our cloud waitlist to get early access. + {t('proxy.coming_soon')} )} - If your proxy requires a username and password, always provide them separately from the proxy URL. + {t('proxy.alert.title')}
- The right way + {t('proxy.alert.right_way')}
- Proxy URL: http://proxy.com:1337 + {t('proxy.alert.proxy_url')} http://proxy.com:1337
- Username: myusername + {t('proxy.alert.username')} myusername
- Password: mypassword + {t('proxy.alert.password')} mypassword

- The wrong way + {t('proxy.alert.wrong_way')}
- Proxy URL: http://myusername:mypassword@proxy.com:1337 + {t('proxy.alert.proxy_url')} http://myusername:mypassword@proxy.com:1337
); }; -export default ProxyForm; +export default ProxyForm; \ No newline at end of file From 1529629d9e81621a9c06c7a1d35597433c875e8f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:10:41 +0530 Subject: [PATCH 070/238] feat: add german translation for apikey page --- public/locales/de.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index ef0cc31a1..c0ba6a27b 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -92,5 +92,30 @@ "remove_success": "Proxy-Konfiguration erfolgreich entfernt", "remove_error": "Fehler beim Entfernen der Proxy-Konfiguration. Bitte erneut versuchen." } + }, + "apikey": { + "title": "API-Schlüssel verwalten", + "default_name": "Maxun API-Schlüssel", + "table": { + "name": "API-Schlüssel Name", + "key": "API-Schlüssel", + "actions": "Aktionen" + }, + "actions": { + "copy": "Kopieren", + "show": "Anzeigen", + "hide": "Ausblenden", + "delete": "Löschen" + }, + "no_key_message": "Sie haben noch keinen API-Schlüssel generiert.", + "generate_button": "API-Schlüssel generieren", + "notifications": { + "fetch_error": "API-Schlüssel konnte nicht abgerufen werden - ${error}", + "generate_success": "API-Schlüssel erfolgreich generiert", + "generate_error": "API-Schlüssel konnte nicht generiert werden - ${error}", + "delete_success": "API-Schlüssel erfolgreich gelöscht", + "delete_error": "API-Schlüssel konnte nicht gelöscht werden - ${error}", + "copy_success": "API-Schlüssel erfolgreich kopiert" + } } } From 114cbdda6f40425b59a64ca89447e68efadb8f27 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:11:10 +0530 Subject: [PATCH 071/238] feat: add english translation for apikey page --- public/locales/en.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index ed5582bfe..5dcce1a6a 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -95,5 +95,30 @@ "remove_success": "Proxy configuration removed successfully", "remove_error": "Failed to remove proxy configuration. Try again." } + }, + "apikey": { + "title": "Manage Your API Key", + "default_name": "Maxun API Key", + "table": { + "name": "API Key Name", + "key": "API Key", + "actions": "Actions" + }, + "actions": { + "copy": "Copy", + "show": "Show", + "hide": "Hide", + "delete": "Delete" + }, + "no_key_message": "You haven't generated an API key yet.", + "generate_button": "Generate API Key", + "notifications": { + "fetch_error": "Failed to fetch API Key - ${error}", + "generate_success": "Generated API Key successfully", + "generate_error": "Failed to generate API Key - ${error}", + "delete_success": "API Key deleted successfully", + "delete_error": "Failed to delete API Key - ${error}", + "copy_success": "Copied API Key successfully" + } } } \ No newline at end of file From 03aa00e2f8dbb6bf09de05ee05d231dcd6b823fa Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:11:42 +0530 Subject: [PATCH 072/238] feat: add japanese translation for apikey page --- public/locales/ja.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 2d7adc25c..53d0d0235 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -93,5 +93,30 @@ "remove_success": "プロキシ設定が正常に削除されました", "remove_error": "プロキシ設定の削除に失敗しました。もう一度お試しください。" } + }, + "apikey": { + "title": "APIキーの管理", + "default_name": "Maxun APIキー", + "table": { + "name": "APIキー名", + "key": "APIキー", + "actions": "アクション" + }, + "actions": { + "copy": "コピー", + "show": "表示", + "hide": "非表示", + "delete": "削除" + }, + "no_key_message": "APIキーはまだ生成されていません。", + "generate_button": "APIキーを生成", + "notifications": { + "fetch_error": "APIキーの取得に失敗しました - ${error}", + "generate_success": "APIキーが正常に生成されました", + "generate_error": "APIキーの生成に失敗しました - ${error}", + "delete_success": "APIキーが正常に削除されました", + "delete_error": "APIキーの削除に失敗しました - ${error}", + "copy_success": "APIキーがコピーされました" + } } } From 33ffc445717dc0fd262b4925467a2f80723f3815 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:12:26 +0530 Subject: [PATCH 073/238] feat: add chinese translation for apikey page --- public/locales/zh.json | 55 ++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index 52b2ce3ef..2e9ec2b2b 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -71,27 +71,52 @@ "test_proxy": "测试代理", "remove_proxy": "删除代理", "table": { - "proxy_url": "代理URL", - "requires_auth": "需要认证" + "proxy_url": "代理URL", + "requires_auth": "需要认证" }, "coming_soon": "即将推出 - 开源版(基础轮换)和云版(高级轮换)。如果您不想管理基础设施,请加入我们的云服务等候名单以获得早期访问权限。", "join_waitlist": "加入Maxun Cloud等候名单", "alert": { - "title": "如果您的代理需要用户名和密码,请务必将它们与代理URL分开提供。", - "right_way": "正确方式", - "wrong_way": "错误方式", - "proxy_url": "代理URL:", - "username": "用户名:", - "password": "密码:" + "title": "如果您的代理需要用户名和密码,请务必将它们与代理URL分开提供。", + "right_way": "正确方式", + "wrong_way": "错误方式", + "proxy_url": "代理URL:", + "username": "用户名:", + "password": "密码:" }, "notifications": { - "config_success": "代理配置提交成功", - "config_error": "提交代理配置失败。请重试。", - "test_success": "代理配置运行正常", - "test_error": "测试代理配置失败。请重试。", - "fetch_success": "成功获取代理配置", - "remove_success": "成功删除代理配置", - "remove_error": "删除代理配置失败。请重试。" + "config_success": "代理配置提交成功", + "config_error": "提交代理配置失败。请重试。", + "test_success": "代理配置运行正常", + "test_error": "测试代理配置失败。请重试。", + "fetch_success": "成功获取代理配置", + "remove_success": "成功删除代理配置", + "remove_error": "删除代理配置失败。请重试。" + } + }, + "apikey": { + "title": "管理API密钥", + "default_name": "Maxun API密钥", + "table": { + "name": "API密钥名称", + "key": "API密钥", + "actions": "操作" + }, + "actions": { + "copy": "复制", + "show": "显示", + "hide": "隐藏", + "delete": "删除" + }, + "no_key_message": "您还未生成API密钥。", + "generate_button": "生成API密钥", + "notifications": { + "fetch_error": "获取API密钥失败 - ${error}", + "generate_success": "API密钥生成成功", + "generate_error": "生成API密钥失败 - ${error}", + "delete_success": "API密钥删除成功", + "delete_error": "删除API密钥失败 - ${error}", + "copy_success": "API密钥复制成功" } } } \ No newline at end of file From a2e3d0fe26829849c2fd4917d1f7d6c28e237bb1 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:13:01 +0530 Subject: [PATCH 074/238] feat: add spanish translation for apikey page --- public/locales/es.json | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/public/locales/es.json b/public/locales/es.json index bc62d2a7d..5612fc25b 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -93,5 +93,30 @@ "remove_success": "Configuración del proxy eliminada con éxito", "remove_error": "Error al eliminar la configuración del proxy. Inténtelo de nuevo." } - } + }, + "apikey": { + "title": "Gestionar tu Clave API", + "default_name": "Clave API de Maxun", + "table": { + "name": "Nombre de la Clave API", + "key": "Clave API", + "actions": "Acciones" + }, + "actions": { + "copy": "Copiar", + "show": "Mostrar", + "hide": "Ocultar", + "delete": "Eliminar" + }, + "no_key_message": "Aún no has generado una clave API.", + "generate_button": "Generar Clave API", + "notifications": { + "fetch_error": "Error al obtener la clave API - ${error}", + "generate_success": "Clave API generada con éxito", + "generate_error": "Error al generar la clave API - ${error}", + "delete_success": "Clave API eliminada con éxito", + "delete_error": "Error al eliminar la clave API - ${error}", + "copy_success": "Clave API copiada con éxito" + } +} } \ No newline at end of file From 52d024916193a718d9fafd6f3b7213e56df25c93 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:13:44 +0530 Subject: [PATCH 075/238] feat: add translation for apikey page --- src/components/organisms/ApiKey.tsx | 38 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/components/organisms/ApiKey.tsx b/src/components/organisms/ApiKey.tsx index e6a00a914..37a72764b 100644 --- a/src/components/organisms/ApiKey.tsx +++ b/src/components/organisms/ApiKey.tsx @@ -19,6 +19,7 @@ import styled from 'styled-components'; import axios from 'axios'; import { useGlobalInfoStore } from '../../context/globalInfo'; import { apiUrl } from '../../apiConfig'; +import { useTranslation } from 'react-i18next'; const Container = styled(Box)` display: flex; @@ -29,24 +30,21 @@ const Container = styled(Box)` `; const ApiKeyManager = () => { + const { t } = useTranslation(); const [apiKey, setApiKey] = useState(null); - const [apiKeyName, setApiKeyName] = useState('Maxun API Key'); + const [apiKeyName, setApiKeyName] = useState(t('apikey.default_name')); const [loading, setLoading] = useState(true); const [showKey, setShowKey] = useState(false); const [copySuccess, setCopySuccess] = useState(false); const { notify } = useGlobalInfoStore(); - - - - useEffect(() => { const fetchApiKey = async () => { try { const { data } = await axios.get(`${apiUrl}/auth/api-key`); setApiKey(data.api_key); } catch (error: any) { - notify('error', `Failed to fetch API Key - ${error.message}`); + notify('error', t('apikey.notifications.fetch_error', { error: error.message })); } finally { setLoading(false); } @@ -62,9 +60,9 @@ const ApiKeyManager = () => { const { data } = await axios.post(`${apiUrl}/auth/generate-api-key`); setApiKey(data.api_key); - notify('success', `Generated API Key successfully`); + notify('success', t('apikey.notifications.generate_success')); } catch (error: any) { - notify('error', `Failed to generate API Key - ${error.message}`); + notify('error', t('apikey.notifications.generate_error', { error: error.message })); } finally { setLoading(false); } @@ -75,9 +73,9 @@ const ApiKeyManager = () => { try { await axios.delete(`${apiUrl}/auth/delete-api-key`); setApiKey(null); - notify('success', 'API Key deleted successfully'); + notify('success', t('apikey.notifications.delete_success')); } catch (error: any) { - notify('error', `Failed to delete API Key - ${error.message}`); + notify('error', t('apikey.notifications.delete_error', { error: error.message })); } finally { setLoading(false); } @@ -88,7 +86,7 @@ const ApiKeyManager = () => { navigator.clipboard.writeText(apiKey); setCopySuccess(true); setTimeout(() => setCopySuccess(false), 2000); - notify('info', 'Copied API Key successfully'); + notify('info', t('apikey.notifications.copy_success')); } }; @@ -111,16 +109,16 @@ const ApiKeyManager = () => { return ( - Manage Your API Key + {t('apikey.title')} {apiKey ? ( - API Key Name - API Key - Actions + {t('apikey.table.name')} + {t('apikey.table.key')} + {t('apikey.table.actions')} @@ -128,17 +126,17 @@ const ApiKeyManager = () => { {apiKeyName} {showKey ? `${apiKey?.substring(0, 10)}...` : '***************'} - + - + setShowKey(!showKey)}> - + @@ -150,9 +148,9 @@ const ApiKeyManager = () => { ) : ( <> - You haven't generated an API key yet. + {t('apikey.no_key_message')} )} From 29ed5638df3caf2610f2b0306c687d42454419c0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:31:41 +0530 Subject: [PATCH 076/238] feat: add spanish translation for action description box --- public/locales/es.json | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/public/locales/es.json b/public/locales/es.json index 5612fc25b..111f831d9 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -118,5 +118,29 @@ "delete_error": "Error al eliminar la clave API - ${error}", "copy_success": "Clave API copiada con éxito" } -} + }, + "action_description": { + "text": { + "title": "Capturar Texto", + "description": "Pase el cursor sobre los textos que desea extraer y haga clic para seleccionarlos" + }, + "screenshot": { + "title": "Capturar Pantalla", + "description": "Capture una captura de pantalla parcial o completa de la página actual." + }, + "list": { + "title": "Capturar Lista", + "description": "Pase el cursor sobre la lista que desea extraer. Una vez seleccionada, puede pasar el cursor sobre todos los textos dentro de la lista seleccionada. Haga clic para seleccionarlos." + }, + "default": { + "title": "¿Qué datos desea extraer?", + "description": "Un robot está diseñado para realizar una acción a la vez. Puede elegir cualquiera de las siguientes opciones." + }, + "list_stages": { + "initial": "Seleccione la lista que desea extraer junto con los textos que contiene", + "pagination": "Seleccione cómo puede el robot capturar el resto de la lista", + "limit": "Elija el número de elementos a extraer", + "complete": "Captura completada" + } + } } \ No newline at end of file From 906b752f89d2a56c769b2259c12b911a176f907d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:32:06 +0530 Subject: [PATCH 077/238] feat: add chinese translation for action description box --- public/locales/zh.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 2e9ec2b2b..6cc3d56e7 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -118,5 +118,29 @@ "delete_error": "删除API密钥失败 - ${error}", "copy_success": "API密钥复制成功" } + }, + "action_description": { + "text": { + "title": "捕获文本", + "description": "将鼠标悬停在要提取的文本上并点击选择" + }, + "screenshot": { + "title": "捕获截图", + "description": "捕获当前页面的部分或全部截图。" + }, + "list": { + "title": "捕获列表", + "description": "将鼠标悬停在要提取的列表上。选择后,您可以将鼠标悬停在所选列表中的所有文本上。点击选择它们。" + }, + "default": { + "title": "您想提取什么数据?", + "description": "机器人设计为一次执行一个操作。您可以选择以下任何选项。" + }, + "list_stages": { + "initial": "选择要提取的列表及其中的文本", + "pagination": "选择机器人如何捕获列表的其余部分", + "limit": "选择要提取的项目数量", + "complete": "捕获完成" + } } } \ No newline at end of file From 9e80bf3373e19b64b7d0adfbdd50615ce83eaa7e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:32:34 +0530 Subject: [PATCH 078/238] feat: add japanese translation for action description box --- public/locales/ja.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 53d0d0235..fc25bec05 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -118,5 +118,29 @@ "delete_error": "APIキーの削除に失敗しました - ${error}", "copy_success": "APIキーがコピーされました" } + }, + "action_description": { + "text": { + "title": "テキストを取得", + "description": "抽出したいテキストにカーソルを合わせ、クリックして選択してください" + }, + "screenshot": { + "title": "スクリーンショットを取得", + "description": "現在のページの部分的または全体のスクリーンショットを取得します。" + }, + "list": { + "title": "リストを取得", + "description": "抽出したいリストにカーソルを合わせてください。選択後、選択したリスト内のすべてのテキストにカーソルを合わせることができます。クリックして選択してください。" + }, + "default": { + "title": "どのデータを抽出しますか?", + "description": "ロボットは一度に1つのアクションを実行するように設計されています。以下のオプションから選択できます。" + }, + "list_stages": { + "initial": "抽出したいリストとその中のテキストを選択してください", + "pagination": "ロボットがリストの残りをどのように取得するか選択してください", + "limit": "抽出するアイテムの数を選択してください", + "complete": "取得が完了しました" + } } } From 4b07690cfe41c287077fef5964a94de41386e69d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:32:57 +0530 Subject: [PATCH 079/238] feat: add english translation for action description box --- public/locales/en.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 5dcce1a6a..b44798cf9 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -120,5 +120,29 @@ "delete_error": "Failed to delete API Key - ${error}", "copy_success": "Copied API Key successfully" } + }, + "action_description": { + "text": { + "title": "Capture Text", + "description": "Hover over the texts you want to extract and click to select them" + }, + "screenshot": { + "title": "Capture Screenshot", + "description": "Capture a partial or full page screenshot of the current page." + }, + "list": { + "title": "Capture List", + "description": "Hover over the list you want to extract. Once selected, you can hover over all texts inside the list you selected. Click to select them." + }, + "default": { + "title": "What data do you want to extract?", + "description": "A robot is designed to perform one action at a time. You can choose any of the options below." + }, + "list_stages": { + "initial": "Select the list you want to extract along with the texts inside it", + "pagination": "Select how the robot can capture the rest of the list", + "limit": "Choose the number of items to extract", + "complete": "Capture is complete" + } } } \ No newline at end of file From 6091df8d9552fd8823d8a6ddb40967da12819b40 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:33:21 +0530 Subject: [PATCH 080/238] feat: add german translation for action description box --- public/locales/de.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index c0ba6a27b..5662134ec 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -117,5 +117,29 @@ "delete_error": "API-Schlüssel konnte nicht gelöscht werden - ${error}", "copy_success": "API-Schlüssel erfolgreich kopiert" } + }, + "action_description": { + "text": { + "title": "Text erfassen", + "description": "Fahren Sie über die Texte, die Sie extrahieren möchten, und klicken Sie, um sie auszuwählen" + }, + "screenshot": { + "title": "Screenshot erfassen", + "description": "Erfassen Sie einen Teil- oder Vollbildschirmfoto der aktuellen Seite." + }, + "list": { + "title": "Liste erfassen", + "description": "Fahren Sie über die Liste, die Sie extrahieren möchten. Nach der Auswahl können Sie über alle Texte in der ausgewählten Liste fahren. Klicken Sie zum Auswählen." + }, + "default": { + "title": "Welche Daten möchten Sie extrahieren?", + "description": "Ein Roboter ist darauf ausgelegt, eine Aktion nach der anderen auszuführen. Sie können eine der folgenden Optionen wählen." + }, + "list_stages": { + "initial": "Wählen Sie die Liste aus, die Sie extrahieren möchten, zusammen mit den darin enthaltenen Texten", + "pagination": "Wählen Sie aus, wie der Roboter den Rest der Liste erfassen kann", + "limit": "Wählen Sie die Anzahl der zu extrahierenden Elemente", + "complete": "Erfassung ist abgeschlossen" + } } } From 598609e29db157d82cde8b991d02f8e93c33b75f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 21:33:55 +0530 Subject: [PATCH 081/238] feat: add translation for action description box --- .../molecules/ActionDescriptionBox.tsx | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/components/molecules/ActionDescriptionBox.tsx b/src/components/molecules/ActionDescriptionBox.tsx index cad962c76..190c58384 100644 --- a/src/components/molecules/ActionDescriptionBox.tsx +++ b/src/components/molecules/ActionDescriptionBox.tsx @@ -3,6 +3,7 @@ import styled from 'styled-components'; import { Typography, FormControlLabel, Checkbox, Box } from '@mui/material'; import { useActionContext } from '../../context/browserActions'; import MaxunLogo from "../../assets/maxunlogo.png"; +import { useTranslation } from 'react-i18next'; const CustomBoxContainer = styled.div` position: relative; @@ -44,6 +45,7 @@ const Content = styled.div` `; const ActionDescriptionBox = () => { + const { t } = useTranslation(); const { getText, getScreenshot, getList, captureStage } = useActionContext() as { getText: boolean; getScreenshot: boolean; @@ -52,36 +54,36 @@ const ActionDescriptionBox = () => { }; const messages = [ - { stage: 'initial' as const, text: 'Select the list you want to extract along with the texts inside it' }, - { stage: 'pagination' as const, text: 'Select how the robot can capture the rest of the list' }, - { stage: 'limit' as const, text: 'Choose the number of items to extract' }, - { stage: 'complete' as const, text: 'Capture is complete' }, + { stage: 'initial' as const, text: t('action_description.list_stages.initial') }, + { stage: 'pagination' as const, text: t('action_description.list_stages.pagination') }, + { stage: 'limit' as const, text: t('action_description.list_stages.limit') }, + { stage: 'complete' as const, text: t('action_description.list_stages.complete') }, ]; - const stages = messages.map(({ stage }) => stage); // Create a list of stages - const currentStageIndex = stages.indexOf(captureStage); // Get the index of the current stage + const stages = messages.map(({ stage }) => stage); + const currentStageIndex = stages.indexOf(captureStage); const renderActionDescription = () => { if (getText) { return ( <> - Capture Text - Hover over the texts you want to extract and click to select them + {t('action_description.text.title')} + {t('action_description.text.description')} ); } else if (getScreenshot) { return ( <> - Capture Screenshot - Capture a partial or full page screenshot of the current page. + {t('action_description.screenshot.title')} + {t('action_description.screenshot.description')} ); } else if (getList) { return ( <> - Capture List + {t('action_description.list.title')} - Hover over the list you want to extract. Once selected, you can hover over all texts inside the list you selected. Click to select them. + {t('action_description.list.description')} {messages.map(({ stage, text }, index) => ( @@ -89,7 +91,7 @@ const ActionDescriptionBox = () => { key={stage} control={ } @@ -102,8 +104,8 @@ const ActionDescriptionBox = () => { } else { return ( <> - What data do you want to extract? - A robot is designed to perform one action at a time. You can choose any of the options below. + {t('action_description.default.title')} + {t('action_description.default.description')} ); } @@ -111,7 +113,7 @@ const ActionDescriptionBox = () => { return ( - + {renderActionDescription()} @@ -120,4 +122,4 @@ const ActionDescriptionBox = () => { ); }; -export default ActionDescriptionBox; +export default ActionDescriptionBox; \ No newline at end of file From 7cc9947b2acf2938ef7b799f7d535655b37158bc Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 20 Dec 2024 21:59:34 +0530 Subject: [PATCH 082/238] feat: auto logout after certain hours of inactivity --- src/context/auth.tsx | 88 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 8 deletions(-) diff --git a/src/context/auth.tsx b/src/context/auth.tsx index 5c46e4de7..a02711f3d 100644 --- a/src/context/auth.tsx +++ b/src/context/auth.tsx @@ -1,4 +1,4 @@ -import { useReducer, createContext, useEffect } from 'react'; +import { useReducer, createContext, useEffect, useCallback } from 'react'; import axios from 'axios'; import { useNavigate } from 'react-router-dom'; import { apiUrl } from "../apiConfig"; @@ -14,12 +14,16 @@ interface ActionType { type InitialStateType = { user: any; + lastActivityTime?: number; }; const initialState = { user: null, + lastActivityTime: Date.now(), }; +const AUTO_LOGOUT_TIME = 4 * 60 * 60 * 1000; // 4 hours in milliseconds + const AuthContext = createContext<{ state: InitialStateType; dispatch: React.Dispatch; @@ -34,11 +38,13 @@ const reducer = (state: InitialStateType, action: ActionType) => { return { ...state, user: action.payload, + lastActivityTime: Date.now(), }; case 'LOGOUT': return { ...state, user: null, + lastActivityTime: undefined, }; default: return state; @@ -50,6 +56,39 @@ const AuthProvider = ({ children }: AuthProviderProps) => { const navigate = useNavigate(); axios.defaults.withCredentials = true; + const handleLogout = useCallback(async () => { + try { + await axios.get(`${apiUrl}/auth/logout`); + dispatch({ type: 'LOGOUT' }); + window.localStorage.removeItem('user'); + navigate('/login'); + } catch (err) { + console.error('Logout error:', err); + } + }, [navigate]); + + const checkAutoLogout = useCallback(() => { + if (state.user && state.lastActivityTime) { + const currentTime = Date.now(); + const timeSinceLastActivity = currentTime - state.lastActivityTime; + + if (timeSinceLastActivity >= AUTO_LOGOUT_TIME) { + handleLogout(); + } + } + }, [state.user, state.lastActivityTime, handleLogout]); + + // Update last activity time on user interactions + const updateActivityTime = useCallback(() => { + if (state.user) { + dispatch({ + type: 'LOGIN', + payload: state.user // Reuse existing user data + }); + } + }, [state.user]); + + // Initialize user from localStorage useEffect(() => { const storedUser = window.localStorage.getItem('user'); if (storedUser) { @@ -57,21 +96,54 @@ const AuthProvider = ({ children }: AuthProviderProps) => { } }, []); + // Set up activity listeners + useEffect(() => { + if (state.user) { + // List of events to track for user activity + const events = ['mousedown', 'keydown', 'scroll', 'touchstart']; + + // Throttled event handler + let timeoutId: NodeJS.Timeout; + const handleActivity = () => { + if (timeoutId) { + clearTimeout(timeoutId); + } + timeoutId = setTimeout(updateActivityTime, 1000); + }; + + // Add event listeners + events.forEach(event => { + window.addEventListener(event, handleActivity); + }); + + // Set up periodic check for auto logout + const checkInterval = setInterval(checkAutoLogout, 60000); // Check every minute + + // Cleanup + return () => { + events.forEach(event => { + window.removeEventListener(event, handleActivity); + }); + clearInterval(checkInterval); + if (timeoutId) { + clearTimeout(timeoutId); + } + }; + } + }, [state.user, updateActivityTime, checkAutoLogout]); + axios.interceptors.response.use( function (response) { return response; }, function (error) { const res = error.response; - if (res.status === 401 && res.config && !res.config.__isRetryRequest) { - return new Promise((resolve, reject) => { - axios - .get(`${apiUrl}/auth/logout`) + if (res?.status === 401 && res.config && !res.config.__isRetryRequest) { + return new Promise((_, reject) => { + handleLogout() .then(() => { console.log('/401 error > logout'); - dispatch({ type: 'LOGOUT' }); - window.localStorage.removeItem('user'); - navigate('/login'); + reject(error); }) .catch((err) => { console.error('AXIOS INTERCEPTORS ERROR:', err); From 25e109e29e095207ee93aad69c144b5fcf07a5b9 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:04:10 +0530 Subject: [PATCH 083/238] feat: add german translation for right side panel --- public/locales/de.json | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 5662134ec..21b9ccdff 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -141,5 +141,56 @@ "limit": "Wählen Sie die Anzahl der zu extrahierenden Elemente", "complete": "Erfassung ist abgeschlossen" } + }, + "right_panel": { + "buttons": { + "capture_list": "Liste erfassen", + "capture_text": "Text erfassen", + "capture_screenshot": "Screenshot erfassen", + "confirm": "Bestätigen", + "discard": "Verwerfen", + "confirm_capture": "Erfassung bestätigen", + "confirm_pagination": "Paginierung bestätigen", + "confirm_limit": "Limit bestätigen", + "finish_capture": "Erfassung abschließen" + }, + "screenshot": { + "capture_fullpage": "Vollständige Seite erfassen", + "capture_visible": "Sichtbaren Bereich erfassen", + "display_fullpage": "Vollständige Seite Screenshot", + "display_visible": "Sichtbarer Bereich Screenshot" + }, + "pagination": { + "title": "Wie können wir das nächste Listenelement auf der Seite finden?", + "click_next": "Auf 'Weiter' klicken, um zur nächsten Seite zu navigieren", + "click_load_more": "Auf 'Mehr laden' klicken, um weitere Elemente zu laden", + "scroll_down": "Nach unten scrollen, um mehr Elemente zu laden", + "scroll_up": "Nach oben scrollen, um mehr Elemente zu laden", + "none": "Keine weiteren Elemente zu laden" + }, + "limit": { + "title": "Wie viele Zeilen möchten Sie maximal extrahieren?", + "custom": "Benutzerdefiniert", + "enter_number": "Nummer eingeben" + }, + "fields": { + "label": "Bezeichnung", + "data": "Daten", + "field_label": "Feldbezeichnung", + "field_data": "Felddaten" + }, + "messages": { + "list_selected": "Liste erfolgreich ausgewählt" + }, + "errors": { + "select_pagination": "Bitte wählen Sie einen Paginierungstyp aus.", + "select_pagination_element": "Bitte wählen Sie zuerst das Paginierungselement aus.", + "select_limit": "Bitte wählen Sie ein Limit oder geben Sie ein benutzerdefiniertes Limit ein.", + "invalid_limit": "Bitte geben Sie ein gültiges Limit ein.", + "confirm_text_fields": "Bitte bestätigen Sie alle Textfelder", + "unable_create_settings": "Listeneinstellungen können nicht erstellt werden. Stellen Sie sicher, dass Sie ein Feld für die Liste definiert haben.", + "capture_text_discarded": "Texterfassung verworfen", + "capture_list_discarded": "Listenerfassung verworfen" + } } } From 50a2321425b98942490e63c98d2c5bf3dddb6988 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:13:18 +0530 Subject: [PATCH 084/238] feat: add german translation for right side panel --- public/locales/de.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/locales/de.json b/public/locales/de.json index 21b9ccdff..c72edeeac 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -152,7 +152,8 @@ "confirm_capture": "Erfassung bestätigen", "confirm_pagination": "Paginierung bestätigen", "confirm_limit": "Limit bestätigen", - "finish_capture": "Erfassung abschließen" + "finish_capture": "Erfassung abschließen", + "finish": "Fertig" }, "screenshot": { "capture_fullpage": "Vollständige Seite erfassen", From e8c8559a78849c5c4e4438a6f4b0f62c3da92efb Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:13:34 +0530 Subject: [PATCH 085/238] feat: add english translation for right side panel --- public/locales/en.json | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index b44798cf9..661fe29ad 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -144,5 +144,57 @@ "limit": "Choose the number of items to extract", "complete": "Capture is complete" } + }, + "right_panel": { + "buttons": { + "capture_list": "Capture List", + "capture_text": "Capture Text", + "capture_screenshot": "Capture Screenshot", + "confirm": "Confirm", + "discard": "Discard", + "confirm_capture": "Confirm Capture", + "confirm_pagination": "Confirm Pagination", + "confirm_limit": "Confirm Limit", + "finish_capture": "Finish Capture", + "finish": "Finish" + }, + "screenshot": { + "capture_fullpage": "Capture Fullpage", + "capture_visible": "Capture Visible Part", + "display_fullpage": "Take Fullpage Screenshot", + "display_visible": "Take Visible Part Screenshot" + }, + "pagination": { + "title": "How can we find the next list item on the page?", + "click_next": "Click on next to navigate to the next page", + "click_load_more": "Click on load more to load more items", + "scroll_down": "Scroll down to load more items", + "scroll_up": "Scroll up to load more items", + "none": "No more items to load" + }, + "limit": { + "title": "What is the maximum number of rows you want to extract?", + "custom": "Custom", + "enter_number": "Enter number" + }, + "fields": { + "label": "Label", + "data": "Data", + "field_label": "Field Label", + "field_data": "Field Data" + }, + "messages": { + "list_selected": "List Selected Successfully" + }, + "errors": { + "select_pagination": "Please select a pagination type.", + "select_pagination_element": "Please select the pagination element first.", + "select_limit": "Please select a limit or enter a custom limit.", + "invalid_limit": "Please enter a valid limit.", + "confirm_text_fields": "Please confirm all text fields", + "unable_create_settings": "Unable to create list settings. Make sure you have defined a field for the list.", + "capture_text_discarded": "Capture Text Discarded", + "capture_list_discarded": "Capture List Discarded" + } } } \ No newline at end of file From 0b31fc261a1efacb83b5e5e8ca8edd53444138e6 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:14:01 +0530 Subject: [PATCH 086/238] feat: add japanese translation for right side panel --- public/locales/ja.json | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index fc25bec05..8b7acde2e 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -142,5 +142,57 @@ "limit": "抽出するアイテムの数を選択してください", "complete": "取得が完了しました" } + }, + "right_panel": { + "buttons": { + "capture_list": "リストを取得", + "capture_text": "テキストを取得", + "capture_screenshot": "スクリーンショットを取得", + "confirm": "確認", + "discard": "破棄", + "confirm_capture": "取得を確認", + "confirm_pagination": "ページネーションを確認", + "confirm_limit": "制限を確認", + "finish_capture": "取得を完了", + "finish": "完了" + }, + "screenshot": { + "capture_fullpage": "フルページを取得", + "capture_visible": "表示部分を取得", + "display_fullpage": "フルページスクリーンショットを撮影", + "display_visible": "表示部分のスクリーンショットを撮影" + }, + "pagination": { + "title": "次のリスト項目をページ上でどのように見つけますか?", + "click_next": "次へをクリックして次のページへ移動", + "click_load_more": "もっと読み込むをクリックして項目を追加", + "scroll_down": "下にスクロールして項目を追加", + "scroll_up": "上にスクロールして項目を追加", + "none": "これ以上読み込む項目はありません" + }, + "limit": { + "title": "抽出する最大行数はいくつですか?", + "custom": "カスタム", + "enter_number": "数値を入力" + }, + "fields": { + "label": "ラベル", + "data": "データ", + "field_label": "フィールドラベル", + "field_data": "フィールドデータ" + }, + "messages": { + "list_selected": "リストが正常に選択されました" + }, + "errors": { + "select_pagination": "ページネーションタイプを選択してください。", + "select_pagination_element": "まずページネーション要素を選択してください。", + "select_limit": "制限を選択するかカスタム制限を入力してください。", + "invalid_limit": "有効な制限を入力してください。", + "confirm_text_fields": "すべてのテキストフィールドを確認してください", + "unable_create_settings": "リスト設定を作成できません。リストのフィールドを定義したことを確認してください。", + "capture_text_discarded": "テキスト取得が破棄されました", + "capture_list_discarded": "リスト取得が破棄されました" + } } } From 6b560c1a248f2bab3814d022654bb806cc9dc43e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:14:21 +0530 Subject: [PATCH 087/238] feat: add spanish translation for right side panel --- public/locales/es.json | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 111f831d9..7a779e146 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -142,5 +142,57 @@ "limit": "Elija el número de elementos a extraer", "complete": "Captura completada" } + }, + "right_panel": { + "buttons": { + "capture_list": "Capturar Lista", + "capture_text": "Capturar Texto", + "capture_screenshot": "Capturar Pantalla", + "confirm": "Confirmar", + "discard": "Descartar", + "confirm_capture": "Confirmar Captura", + "confirm_pagination": "Confirmar Paginación", + "confirm_limit": "Confirmar Límite", + "finish_capture": "Finalizar Captura", + "finish": "Finalizar" + }, + "screenshot": { + "capture_fullpage": "Capturar Página Completa", + "capture_visible": "Capturar Parte Visible", + "display_fullpage": "Capturar Screenshot de Página Completa", + "display_visible": "Capturar Screenshot de Parte Visible" + }, + "pagination": { + "title": "¿Cómo podemos encontrar el siguiente elemento de la lista en la página?", + "click_next": "Hacer clic en siguiente para navegar a la siguiente página", + "click_load_more": "Hacer clic en cargar más para cargar más elementos", + "scroll_down": "Desplazarse hacia abajo para cargar más elementos", + "scroll_up": "Desplazarse hacia arriba para cargar más elementos", + "none": "No hay más elementos para cargar" + }, + "limit": { + "title": "¿Cuál es el número máximo de filas que desea extraer?", + "custom": "Personalizado", + "enter_number": "Ingrese número" + }, + "fields": { + "label": "Etiqueta", + "data": "Datos", + "field_label": "Etiqueta del Campo", + "field_data": "Datos del Campo" + }, + "messages": { + "list_selected": "Lista seleccionada exitosamente" + }, + "errors": { + "select_pagination": "Por favor seleccione un tipo de paginación.", + "select_pagination_element": "Por favor seleccione primero el elemento de paginación.", + "select_limit": "Por favor seleccione un límite o ingrese un límite personalizado.", + "invalid_limit": "Por favor ingrese un límite válido.", + "confirm_text_fields": "Por favor confirme todos los campos de texto", + "unable_create_settings": "No se pueden crear las configuraciones de la lista. Asegúrese de haber definido un campo para la lista.", + "capture_text_discarded": "Captura de texto descartada", + "capture_list_discarded": "Captura de lista descartada" + } } } \ No newline at end of file From f33ce5274c30a65a02df0003bbc02db9250e2a26 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:14:41 +0530 Subject: [PATCH 088/238] feat: add chinese translation for right side panel --- public/locales/zh.json | 52 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 6cc3d56e7..b31ac8a53 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -142,5 +142,57 @@ "limit": "选择要提取的项目数量", "complete": "捕获完成" } + }, + "right_panel": { + "buttons": { + "capture_list": "捕获列表", + "capture_text": "捕获文本", + "capture_screenshot": "捕获截图", + "confirm": "确认", + "discard": "放弃", + "confirm_capture": "确认捕获", + "confirm_pagination": "确认分页", + "confirm_limit": "确认限制", + "finish_capture": "完成捕获", + "finish": "完成" + }, + "screenshot": { + "capture_fullpage": "捕获整页", + "capture_visible": "捕获可见部分", + "display_fullpage": "获取整页截图", + "display_visible": "获取可见部分截图" + }, + "pagination": { + "title": "如何在页面上找到下一个列表项?", + "click_next": "点击下一页导航到下一页", + "click_load_more": "点击加载更多来加载更多项目", + "scroll_down": "向下滚动加载更多项目", + "scroll_up": "向上滚动加载更多项目", + "none": "没有更多项目可加载" + }, + "limit": { + "title": "您想要提取的最大行数是多少?", + "custom": "自定义", + "enter_number": "输入数字" + }, + "fields": { + "label": "标签", + "data": "数据", + "field_label": "字段标签", + "field_data": "字段数据" + }, + "messages": { + "list_selected": "列表选择成功" + }, + "errors": { + "select_pagination": "请选择分页类型。", + "select_pagination_element": "请先选择分页元素。", + "select_limit": "请选择限制或输入自定义限制。", + "invalid_limit": "请输入有效的限制。", + "confirm_text_fields": "请确认所有文本字段", + "unable_create_settings": "无法创建列表设置。请确保您已为列表定义了字段。", + "capture_text_discarded": "文本捕获已放弃", + "capture_list_discarded": "列表捕获已放弃" + } } } \ No newline at end of file From fa4d8393675daaf538a51088e6b67546dd669fa0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:16:12 +0530 Subject: [PATCH 089/238] feat: add translation for right side panel --- src/components/organisms/RightSidePanel.tsx | 87 +++++++++++---------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/src/components/organisms/RightSidePanel.tsx b/src/components/organisms/RightSidePanel.tsx index 4aaf7b214..224e0954e 100644 --- a/src/components/organisms/RightSidePanel.tsx +++ b/src/components/organisms/RightSidePanel.tsx @@ -22,6 +22,7 @@ import { emptyWorkflow } from "../../shared/constants"; import { getActiveWorkflow } from "../../api/workflow"; import DeleteIcon from '@mui/icons-material/Delete'; import ActionDescriptionBox from '../molecules/ActionDescriptionBox'; +import { useTranslation } from 'react-i18next'; const fetchWorkflow = (id: string, callback: (response: WorkflowFile) => void) => { getActiveWorkflow(id).then( @@ -60,6 +61,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture const { getText, startGetText, stopGetText, getScreenshot, startGetScreenshot, stopGetScreenshot, getList, startGetList, stopGetList, startPaginationMode, stopPaginationMode, paginationType, updatePaginationType, limitType, customLimit, updateLimitType, updateCustomLimit, stopLimitMode, startLimitMode, captureStage, setCaptureStage } = useActionContext(); const { browserSteps, updateBrowserTextStepLabel, deleteBrowserStep, addScreenshotStep, updateListTextFieldLabel, removeListTextField } = useBrowserSteps(); const { id, socket } = useSocketStore(); + const { t } = useTranslation(); const workflowHandler = useCallback((data: WorkflowFile) => { setWorkflow(data); @@ -139,7 +141,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture setTextLabels(prevLabels => ({ ...prevLabels, [id]: label })); } if (!label.trim()) { - setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' })); + setErrors(prevErrors => ({ ...prevErrors, [id]: t('right_panel.errors.label_required') })); } else { setErrors(prevErrors => ({ ...prevErrors, [id]: '' })); } @@ -151,7 +153,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture updateBrowserTextStepLabel(id, label); setConfirmedTextSteps(prev => ({ ...prev, [id]: true })); } else { - setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' })); + setErrors(prevErrors => ({ ...prevErrors, [id]: t('right_panel.errors.label_required') })); } }; @@ -213,7 +215,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture const stopCaptureAndEmitGetTextSettings = useCallback(() => { const hasUnconfirmedTextSteps = browserSteps.some(step => step.type === 'text' && !confirmedTextSteps[step.id]); if (hasUnconfirmedTextSteps) { - notify('error', 'Please confirm all text fields'); + notify('error', t('right_panel.errors.confirm_text_fields')); return; } stopGetText(); @@ -278,7 +280,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture if (settings) { socket?.emit('action', { action: 'scrapeList', settings }); } else { - notify('error', 'Unable to create list settings. Make sure you have defined a field for the list.'); + notify('error', t('right_panel.errors.unable_create_settings')); } handleStopGetList(); onFinishCapture(); @@ -296,13 +298,13 @@ export const RightSidePanel: React.FC = ({ onFinishCapture case 'pagination': if (!paginationType) { - notify('error', 'Please select a pagination type.'); + notify('error', t('right_panel.errors.select_pagination')); return; } const settings = getListSettingsObject(); const paginationSelector = settings.pagination?.selector; if (['clickNext', 'clickLoadMore'].includes(paginationType) && !paginationSelector) { - notify('error', 'Please select the pagination element first.'); + notify('error', t('right_panel.errors.select_pagination_element')); return; } stopPaginationMode(); @@ -314,12 +316,12 @@ export const RightSidePanel: React.FC = ({ onFinishCapture case 'limit': if (!limitType || (limitType === 'custom' && !customLimit)) { - notify('error', 'Please select a limit or enter a custom limit.'); + notify('error', t('right_panel.errors.select_limit')); return; } const limit = limitType === 'custom' ? parseInt(customLimit) : parseInt(limitType); if (isNaN(limit) || limit <= 0) { - notify('error', 'Please enter a valid limit.'); + notify('error', t('right_panel.errors.invalid_limit')); return; } stopLimitMode(); @@ -348,7 +350,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture setTextLabels({}); setErrors({}); setConfirmedTextSteps({}); - notify('error', 'Capture Text Discarded'); + notify('error', t('right_panel.errors.capture_text_discarded')); }, [browserSteps, stopGetText, deleteBrowserStep]); const discardGetList = useCallback(() => { @@ -363,7 +365,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture setShowLimitOptions(false); setCaptureStage('initial'); setConfirmedListTextFields({}); - notify('error', 'Capture List Discarded'); + notify('error', t('right_panel.errors.capture_list_discarded')); }, [browserSteps, stopGetList, deleteBrowserStep, resetListState]); @@ -402,7 +404,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture */} - {!getText && !getScreenshot && !getList && showCaptureList && } + {!getText && !getScreenshot && !getList && showCaptureList && } {getList && ( <> @@ -411,28 +413,29 @@ export const RightSidePanel: React.FC = ({ onFinishCapture onClick={handleConfirmListCapture} disabled={captureStage === 'initial' ? isConfirmCaptureDisabled : hasUnconfirmedListTextFields} > - {captureStage === 'initial' ? 'Confirm Capture' : - captureStage === 'pagination' ? 'Confirm Pagination' : - captureStage === 'limit' ? 'Confirm Limit' : 'Finish Capture'} + {captureStage === 'initial' ? t('right_panel.buttons.confirm_capture') : + captureStage === 'pagination' ? t('right_panel.buttons.confirm_pagination') : + captureStage === 'limit' ? t('right_panel.buttons.confirm_limit') : + t('right_panel.buttons.finish_capture')} - + )} {showPaginationOptions && ( - How can we find the next list item on the page? - - - - - + {t('right_panel.pagination.title')} + + + + + )} {showLimitOptions && ( -

What is the maximum number of rows you want to extract?

+

{t('right_panel.limit.title')}

= ({ onFinishCapture } label="10" /> } label="100" />
- } label="Custom" /> + } label={t('right_panel.limit.custom')} /> {limitType === 'custom' && ( updateCustomLimit(e.target.value)} - placeholder="Enter number" + placeholder={t('right_panel.limit.enter_number')} sx={{ marginLeft: '10px', '& input': { @@ -467,21 +470,21 @@ export const RightSidePanel: React.FC = ({ onFinishCapture )} - {!getText && !getScreenshot && !getList && showCaptureText && } + {!getText && !getScreenshot && !getList && showCaptureText && } {getText && <> - - + + } - {!getText && !getScreenshot && !getList && showCaptureScreenshot && } + {!getText && !getScreenshot && !getList && showCaptureScreenshot && } {getScreenshot && ( - - - + + + )} @@ -492,7 +495,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture step.type === 'text' && ( <> handleTextLabelChange(step.id, e.target.value)} fullWidth @@ -510,7 +513,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture }} /> = ({ onFinishCapture /> {!confirmedTextSteps[step.id] && ( - - + + )} @@ -535,17 +538,19 @@ export const RightSidePanel: React.FC = ({ onFinishCapture - {`Take ${step.fullPage ? 'Fullpage' : 'Visible Part'} Screenshot`} + {step.fullPage ? + t('right_panel.screenshot.display_fullpage') : + t('right_panel.screenshot.display_visible')} )} {step.type === 'list' && ( <> - List Selected Successfully + {t('right_panel.messages.list_selected')} {Object.entries(step.fields).map(([key, field]) => ( handleTextLabelChange(field.id, e.target.value, step.id, key)} fullWidth @@ -560,7 +565,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture }} /> = ({ onFinishCapture onClick={() => handleListTextFieldConfirm(step.id, key)} disabled={!field.label?.trim()} > - Confirm + {t('right_panel.buttons.confirm')} )} From c0c10c8e80072426876ae695aa8dcbcc55d4ca9b Mon Sep 17 00:00:00 2001 From: Richard <115594235+richardzen@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:18:09 +0530 Subject: [PATCH 090/238] feat: move COMMIT_CONVENTION.md --- .github/COMMIT_CONVENTION.md | 130 +++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 .github/COMMIT_CONVENTION.md diff --git a/.github/COMMIT_CONVENTION.md b/.github/COMMIT_CONVENTION.md new file mode 100644 index 000000000..076ff9cfe --- /dev/null +++ b/.github/COMMIT_CONVENTION.md @@ -0,0 +1,130 @@ +## Git Commit Message Convention + +> This is adapted from [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). + +## Summary + +The Conventional Commits specification is a lightweight convention on top of commit messages. +It provides an easy set of rules for creating an explicit commit history; +which makes it easier to write automated tools on top of. +This convention dovetails with [SemVer](http://semver.org), +by describing the features, fixes, and breaking changes made in commit messages. + +The commit message should be structured as follows: + +--- + +``` +[optional scope]: +[optional body] +[optional footer(s)] +``` +--- + +
+The commit contains the following structural elements, to communicate intent to the +consumers of your library: + +1. **fix:** a commit of the _type_ `fix` patches a bug in your codebase (this correlates with [`PATCH`](http://semver.org/#summary) in Semantic Versioning). +1. **feat:** a commit of the _type_ `feat` introduces a new feature to the codebase (this correlates with [`MINOR`](http://semver.org/#summary) in Semantic Versioning). +1. **BREAKING CHANGE:** a commit that has a footer `BREAKING CHANGE:`, or appends a `!` after the type/scope, introduces a breaking API change (correlating with [`MAJOR`](http://semver.org/#summary) in Semantic Versioning). +A BREAKING CHANGE can be part of commits of any _type_. +1. _types_ other than `fix:` and `feat:` are allowed, for example [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) (based on the [the Angular convention](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)) recommends `build:`, `chore:`, + `ci:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`, and others. +1. _footers_ other than `BREAKING CHANGE: ` may be provided and follow a convention similar to + [git trailer format](https://git-scm.com/docs/git-interpret-trailers). + +Additional types are not mandated by the Conventional Commits specification, and have no implicit effect in Semantic Versioning (unless they include a BREAKING CHANGE). +

+A scope may be provided to a commit's type, to provide additional contextual information and is contained within parenthesis, e.g., `feat(parser): add ability to parse arrays`. + +## Examples + +### Commit message with description and breaking change footer +``` +feat: allow provided config object to extend other configs + +BREAKING CHANGE: `extends` key in config file is now used for extending other config files +``` + +### Commit message with `!` to draw attention to breaking change +``` +feat!: send an email to the customer when a product is shipped +``` + +### Commit message with scope and `!` to draw attention to breaking change +``` +feat(api)!: send an email to the customer when a product is shipped +``` + +### Commit message with both `!` and BREAKING CHANGE footer +``` +chore!: drop support for Node 6 + +BREAKING CHANGE: use JavaScript features not available in Node 6. +``` + +### Commit message with no body +``` +docs: correct spelling of CHANGELOG +``` + +### Commit message with scope +``` +feat(lang): add polish language +``` + +### Commit message with multi-paragraph body and multiple footers +``` +fix: prevent racing of requests + +Introduce a request id and a reference to latest request. Dismiss +incoming responses other than from latest request. + +Remove timeouts which were used to mitigate the racing issue but are +obsolete now. + +Reviewed-by: Z +Refs: #123 +``` + +## Specification + +The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +1. Commits MUST be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed + by the OPTIONAL scope, OPTIONAL `!`, and REQUIRED terminal colon and space. +1. The type `feat` MUST be used when a commit adds a new feature to your application or library. +1. The type `fix` MUST be used when a commit represents a bug fix for your application. +1. A scope MAY be provided after a type. A scope MUST consist of a noun describing a + section of the codebase surrounded by parenthesis, e.g., `fix(parser):` +1. A description MUST immediately follow the colon and space after the type/scope prefix. +The description is a short summary of the code changes, e.g., _fix: array parsing issue when multiple spaces were contained in string_. +1. A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description. +1. A commit body is free-form and MAY consist of any number of newline separated paragraphs. +1. One or more footers MAY be provided one blank line after the body. Each footer MUST consist of + a word token, followed by either a `:` or `#` separator, followed by a string value (this is inspired by the + [git trailer convention](https://git-scm.com/docs/git-interpret-trailers)). +1. A footer's token MUST use `-` in place of whitespace characters, e.g., `Acked-by` (this helps differentiate + the footer section from a multi-paragraph body). An exception is made for `BREAKING CHANGE`, which MAY also be used as a token. +1. A footer's value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer + token/separator pair is observed. +1. Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the + footer. +1. If included as a footer, a breaking change MUST consist of the uppercase text BREAKING CHANGE, followed by a colon, space, and description, e.g., +_BREAKING CHANGE: environment variables now take precedence over config files_. +1. If included in the type/scope prefix, breaking changes MUST be indicated by a + `!` immediately before the `:`. If `!` is used, `BREAKING CHANGE:` MAY be omitted from the footer section, + and the commit description SHALL be used to describe the breaking change. +1. Types other than `feat` and `fix` MAY be used in your commit messages, e.g., _docs: updated ref docs._ +1. The units of information that make up Conventional Commits MUST NOT be treated as case sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase. +1. BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer. + +## Why Use Conventional Commits + +* Automatically generating CHANGELOGs. +* Automatically determining a semantic version bump (based on the types of commits landed). +* Communicating the nature of changes to teammates, the public, and other stakeholders. +* Triggering build and publish processes. +* Making it easier for people to contribute to your projects, by allowing them to explore + a more structured commit history. From 3f34a6c720ca05a34aab703eeb389e5fd86fcbd8 Mon Sep 17 00:00:00 2001 From: Richard <115594235+richardzen@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:18:27 +0530 Subject: [PATCH 091/238] feat: delete .github/.github directory --- .github/.github/COMMIT_CONVENTION.md | 130 --------------------------- 1 file changed, 130 deletions(-) delete mode 100644 .github/.github/COMMIT_CONVENTION.md diff --git a/.github/.github/COMMIT_CONVENTION.md b/.github/.github/COMMIT_CONVENTION.md deleted file mode 100644 index 076ff9cfe..000000000 --- a/.github/.github/COMMIT_CONVENTION.md +++ /dev/null @@ -1,130 +0,0 @@ -## Git Commit Message Convention - -> This is adapted from [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/). - -## Summary - -The Conventional Commits specification is a lightweight convention on top of commit messages. -It provides an easy set of rules for creating an explicit commit history; -which makes it easier to write automated tools on top of. -This convention dovetails with [SemVer](http://semver.org), -by describing the features, fixes, and breaking changes made in commit messages. - -The commit message should be structured as follows: - ---- - -``` -[optional scope]: -[optional body] -[optional footer(s)] -``` ---- - -
-The commit contains the following structural elements, to communicate intent to the -consumers of your library: - -1. **fix:** a commit of the _type_ `fix` patches a bug in your codebase (this correlates with [`PATCH`](http://semver.org/#summary) in Semantic Versioning). -1. **feat:** a commit of the _type_ `feat` introduces a new feature to the codebase (this correlates with [`MINOR`](http://semver.org/#summary) in Semantic Versioning). -1. **BREAKING CHANGE:** a commit that has a footer `BREAKING CHANGE:`, or appends a `!` after the type/scope, introduces a breaking API change (correlating with [`MAJOR`](http://semver.org/#summary) in Semantic Versioning). -A BREAKING CHANGE can be part of commits of any _type_. -1. _types_ other than `fix:` and `feat:` are allowed, for example [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) (based on the [the Angular convention](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)) recommends `build:`, `chore:`, - `ci:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`, and others. -1. _footers_ other than `BREAKING CHANGE: ` may be provided and follow a convention similar to - [git trailer format](https://git-scm.com/docs/git-interpret-trailers). - -Additional types are not mandated by the Conventional Commits specification, and have no implicit effect in Semantic Versioning (unless they include a BREAKING CHANGE). -

-A scope may be provided to a commit's type, to provide additional contextual information and is contained within parenthesis, e.g., `feat(parser): add ability to parse arrays`. - -## Examples - -### Commit message with description and breaking change footer -``` -feat: allow provided config object to extend other configs - -BREAKING CHANGE: `extends` key in config file is now used for extending other config files -``` - -### Commit message with `!` to draw attention to breaking change -``` -feat!: send an email to the customer when a product is shipped -``` - -### Commit message with scope and `!` to draw attention to breaking change -``` -feat(api)!: send an email to the customer when a product is shipped -``` - -### Commit message with both `!` and BREAKING CHANGE footer -``` -chore!: drop support for Node 6 - -BREAKING CHANGE: use JavaScript features not available in Node 6. -``` - -### Commit message with no body -``` -docs: correct spelling of CHANGELOG -``` - -### Commit message with scope -``` -feat(lang): add polish language -``` - -### Commit message with multi-paragraph body and multiple footers -``` -fix: prevent racing of requests - -Introduce a request id and a reference to latest request. Dismiss -incoming responses other than from latest request. - -Remove timeouts which were used to mitigate the racing issue but are -obsolete now. - -Reviewed-by: Z -Refs: #123 -``` - -## Specification - -The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). - -1. Commits MUST be prefixed with a type, which consists of a noun, `feat`, `fix`, etc., followed - by the OPTIONAL scope, OPTIONAL `!`, and REQUIRED terminal colon and space. -1. The type `feat` MUST be used when a commit adds a new feature to your application or library. -1. The type `fix` MUST be used when a commit represents a bug fix for your application. -1. A scope MAY be provided after a type. A scope MUST consist of a noun describing a - section of the codebase surrounded by parenthesis, e.g., `fix(parser):` -1. A description MUST immediately follow the colon and space after the type/scope prefix. -The description is a short summary of the code changes, e.g., _fix: array parsing issue when multiple spaces were contained in string_. -1. A longer commit body MAY be provided after the short description, providing additional contextual information about the code changes. The body MUST begin one blank line after the description. -1. A commit body is free-form and MAY consist of any number of newline separated paragraphs. -1. One or more footers MAY be provided one blank line after the body. Each footer MUST consist of - a word token, followed by either a `:` or `#` separator, followed by a string value (this is inspired by the - [git trailer convention](https://git-scm.com/docs/git-interpret-trailers)). -1. A footer's token MUST use `-` in place of whitespace characters, e.g., `Acked-by` (this helps differentiate - the footer section from a multi-paragraph body). An exception is made for `BREAKING CHANGE`, which MAY also be used as a token. -1. A footer's value MAY contain spaces and newlines, and parsing MUST terminate when the next valid footer - token/separator pair is observed. -1. Breaking changes MUST be indicated in the type/scope prefix of a commit, or as an entry in the - footer. -1. If included as a footer, a breaking change MUST consist of the uppercase text BREAKING CHANGE, followed by a colon, space, and description, e.g., -_BREAKING CHANGE: environment variables now take precedence over config files_. -1. If included in the type/scope prefix, breaking changes MUST be indicated by a - `!` immediately before the `:`. If `!` is used, `BREAKING CHANGE:` MAY be omitted from the footer section, - and the commit description SHALL be used to describe the breaking change. -1. Types other than `feat` and `fix` MAY be used in your commit messages, e.g., _docs: updated ref docs._ -1. The units of information that make up Conventional Commits MUST NOT be treated as case sensitive by implementors, with the exception of BREAKING CHANGE which MUST be uppercase. -1. BREAKING-CHANGE MUST be synonymous with BREAKING CHANGE, when used as a token in a footer. - -## Why Use Conventional Commits - -* Automatically generating CHANGELOGs. -* Automatically determining a semantic version bump (based on the types of commits landed). -* Communicating the nature of changes to teammates, the public, and other stakeholders. -* Triggering build and publish processes. -* Making it easier for people to contribute to your projects, by allowing them to explore - a more structured commit history. From b39fca192571fc8db9cafb4d8a7f20d0b2ad69c7 Mon Sep 17 00:00:00 2001 From: Richard <115594235+richardzen@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:22:33 +0530 Subject: [PATCH 092/238] chore: cleanup some code --- src/context/browserActions.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/context/browserActions.tsx b/src/context/browserActions.tsx index 55ca1b371..fd951f924 100644 --- a/src/context/browserActions.tsx +++ b/src/context/browserActions.tsx @@ -14,8 +14,8 @@ interface ActionContextProps { paginationType: PaginationType; limitType: LimitType; customLimit: string; - captureStage: CaptureStage; // New captureStage property - setCaptureStage: (stage: CaptureStage) => void; // Setter for captureStage + captureStage: CaptureStage; + setCaptureStage: (stage: CaptureStage) => void; startPaginationMode: () => void; startGetText: () => void; stopGetText: () => void; From 018b9cb56caadd787fc02b05d9107be8c04fb2c4 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:26:42 +0530 Subject: [PATCH 093/238] feat: add chinese translation for save recording component --- public/locales/zh.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index b31ac8a53..01bf8e5da 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -194,5 +194,23 @@ "capture_text_discarded": "文本捕获已放弃", "capture_list_discarded": "列表捕获已放弃" } + }, + "save_recording": { + "title": "保存机器人", + "robot_name": "机器人名称", + "buttons": { + "save": "保存", + "confirm": "确认" + }, + "notifications": { + "save_success": "机器人保存成功" + }, + "errors": { + "user_not_logged": "用户未登录。无法保存录制。", + "exists_warning": "已存在同名机器人,请确认是否覆盖机器人。" + }, + "tooltips": { + "saving": "正在优化并保存工作流程" + } } } \ No newline at end of file From 06f0fe6df1586aff5995f043a380b1d47077f9e8 Mon Sep 17 00:00:00 2001 From: Richard <115594235+richardzen@users.noreply.github.com> Date: Fri, 20 Dec 2024 22:27:04 +0530 Subject: [PATCH 094/238] chore: format `concurreny.ts` in maxun-core --- maxun-core/src/utils/concurrency.ts | 48 ++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/maxun-core/src/utils/concurrency.ts b/maxun-core/src/utils/concurrency.ts index e1ebb87b3..56c15fd9f 100644 --- a/maxun-core/src/utils/concurrency.ts +++ b/maxun-core/src/utils/concurrency.ts @@ -3,36 +3,36 @@ */ export default class Concurrency { /** - * Maximum number of workers running in parallel. If set to `null`, there is no limit. - */ + * Maximum number of workers running in parallel. If set to `null`, there is no limit. + */ maxConcurrency: number = 1; /** - * Number of currently active workers. - */ + * Number of currently active workers. + */ activeWorkers: number = 0; /** - * Queue of jobs waiting to be completed. - */ + * Queue of jobs waiting to be completed. + */ private jobQueue: Function[] = []; /** - * "Resolve" callbacks of the waitForCompletion() promises. - */ + * "Resolve" callbacks of the waitForCompletion() promises. + */ private waiting: Function[] = []; /** - * Constructs a new instance of concurrency manager. - * @param {number} maxConcurrency Maximum number of workers running in parallel. - */ + * Constructs a new instance of concurrency manager. + * @param {number} maxConcurrency Maximum number of workers running in parallel. + */ constructor(maxConcurrency: number) { this.maxConcurrency = maxConcurrency; } /** - * Takes a waiting job out of the queue and runs it. - */ + * Takes a waiting job out of the queue and runs it. + */ private runNextJob(): void { const job = this.jobQueue.pop(); @@ -53,12 +53,12 @@ export default class Concurrency { } /** - * Pass a job (a time-demanding async function) to the concurrency manager. \ - * The time of the job's execution depends on the concurrency manager itself - * (given a generous enough `maxConcurrency` value, it might be immediate, - * but this is not guaranteed). - * @param worker Async function to be executed (job to be processed). - */ + * Pass a job (a time-demanding async function) to the concurrency manager. \ + * The time of the job's execution depends on the concurrency manager itself + * (given a generous enough `maxConcurrency` value, it might be immediate, + * but this is not guaranteed). + * @param worker Async function to be executed (job to be processed). + */ addJob(job: () => Promise): void { // console.debug("Adding a worker!"); this.jobQueue.push(job); @@ -72,11 +72,11 @@ export default class Concurrency { } /** - * Waits until there is no running nor waiting job. \ - * If the concurrency manager is idle at the time of calling this function, - * it waits until at least one job is completed (can be "presubscribed"). - * @returns Promise, resolved after there is no running/waiting worker. - */ + * Waits until there is no running nor waiting job. \ + * If the concurrency manager is idle at the time of calling this function, + * it waits until at least one job is completed (can be "presubscribed"). + * @returns Promise, resolved after there is no running/waiting worker. + */ waitForCompletion(): Promise { return new Promise((res) => { this.waiting.push(res); From 81a0a06da6e7d369d0a0b11ade7dcdc6379a3366 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:27:05 +0530 Subject: [PATCH 095/238] feat: add german translation for save recording component --- public/locales/de.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index c72edeeac..5148b2d2c 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -193,5 +193,23 @@ "capture_text_discarded": "Texterfassung verworfen", "capture_list_discarded": "Listenerfassung verworfen" } + }, + "save_recording": { + "title": "Roboter speichern", + "robot_name": "Roboter Name", + "buttons": { + "save": "Speichern", + "confirm": "Bestätigen" + }, + "notifications": { + "save_success": "Roboter erfolgreich gespeichert" + }, + "errors": { + "user_not_logged": "Benutzer nicht angemeldet. Aufnahme kann nicht gespeichert werden.", + "exists_warning": "Ein Roboter mit diesem Namen existiert bereits, bitte bestätigen Sie das Überschreiben des Roboters." + }, + "tooltips": { + "saving": "Workflow wird optimiert und gespeichert" + } } } From 855a1adca2fd607114a85b00a6294a8eeec153a1 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:27:27 +0530 Subject: [PATCH 096/238] feat: add spanish translation for save recording component --- public/locales/es.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 7a779e146..5a42b4317 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -194,5 +194,23 @@ "capture_text_discarded": "Captura de texto descartada", "capture_list_discarded": "Captura de lista descartada" } + }, + "save_recording": { + "title": "Guardar Robot", + "robot_name": "Nombre del Robot", + "buttons": { + "save": "Guardar", + "confirm": "Confirmar" + }, + "notifications": { + "save_success": "Robot guardado exitosamente" + }, + "errors": { + "user_not_logged": "Usuario no conectado. No se puede guardar la grabación.", + "exists_warning": "Ya existe un robot con este nombre, por favor confirme la sobrescritura del robot." + }, + "tooltips": { + "saving": "Optimizando y guardando el flujo de trabajo" + } } } \ No newline at end of file From 05de9fcb74c4bd629559cd04993ab9486315e1a2 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:27:42 +0530 Subject: [PATCH 097/238] feat: add japanese translation for save recording component --- public/locales/ja.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 8b7acde2e..46a75b154 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -194,5 +194,23 @@ "capture_text_discarded": "テキスト取得が破棄されました", "capture_list_discarded": "リスト取得が破棄されました" } + }, + "save_recording": { + "title": "ロボットを保存", + "robot_name": "ロボット名", + "buttons": { + "save": "保存", + "confirm": "確認" + }, + "notifications": { + "save_success": "ロボットが正常に保存されました" + }, + "errors": { + "user_not_logged": "ユーザーがログインしていません。録画を保存できません。", + "exists_warning": "この名前のロボットは既に存在します。ロボットの上書きを確認してください。" + }, + "tooltips": { + "saving": "ワークフローを最適化して保存中" + } } } From 73bdc680d3c15aaf8add117cfb55d477a6b8e76e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:27:59 +0530 Subject: [PATCH 098/238] feat: add english translation for save recording component --- public/locales/en.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 661fe29ad..3a65f8988 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -196,5 +196,23 @@ "capture_text_discarded": "Capture Text Discarded", "capture_list_discarded": "Capture List Discarded" } + }, + "save_recording": { + "title": "Save Robot", + "robot_name": "Robot Name", + "buttons": { + "save": "Save", + "confirm": "Confirm" + }, + "notifications": { + "save_success": "Robot saved successfully" + }, + "errors": { + "user_not_logged": "User not logged in. Cannot save recording.", + "exists_warning": "Robot with this name already exists, please confirm the Robot's overwrite." + }, + "tooltips": { + "saving": "Optimizing and saving the workflow" + } } } \ No newline at end of file From 00c187167cd72c8fb6ce77f10a7dd4394549d003 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:28:31 +0530 Subject: [PATCH 099/238] feat: add translation for save recording component --- src/components/molecules/SaveRecording.tsx | 25 +++++++++++++--------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/components/molecules/SaveRecording.tsx b/src/components/molecules/SaveRecording.tsx index cfebc867b..b30370606 100644 --- a/src/components/molecules/SaveRecording.tsx +++ b/src/components/molecules/SaveRecording.tsx @@ -9,13 +9,14 @@ import { TextField, Typography } from "@mui/material"; import { WarningText } from "../atoms/texts"; import NotificationImportantIcon from "@mui/icons-material/NotificationImportant"; import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; interface SaveRecordingProps { fileName: string; } export const SaveRecording = ({ fileName }: SaveRecordingProps) => { - + const { t } = useTranslation(); const [openModal, setOpenModal] = useState(false); const [needConfirm, setNeedConfirm] = useState(false); const [recordingName, setRecordingName] = useState(fileName); @@ -46,7 +47,7 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { }; const exitRecording = useCallback(async () => { - notify('success', 'Robot saved successfully'); + notify('success', t('save_recording.notifications.save_success')); if (browserId) { await stopRecording(browserId); } @@ -63,7 +64,7 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { setWaitingForSave(true); console.log(`Saving the recording as ${recordingName} for userId ${user.id}`); } else { - console.error('User not logged in. Cannot save recording.'); + console.error(t('save_recording.notifications.user_not_logged')); } }; @@ -77,34 +78,38 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { return (
setOpenModal(false)} modalStyle={modalStyle}>
- Save Robot + {t('save_recording.title')} {needConfirm ? ( - + - Robot with this name already exists, please confirm the Robot's overwrite. + {t('save_recording.warnings.robot_exists')} ) - : + : } {waitingForSave && - + From 0af6cd60710c03ea016b78de7643f140f2188192 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Fri, 20 Dec 2024 22:35:59 +0530 Subject: [PATCH 100/238] feat: add translation for save recording component --- src/components/molecules/SaveRecording.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/molecules/SaveRecording.tsx b/src/components/molecules/SaveRecording.tsx index b30370606..8e1eb462e 100644 --- a/src/components/molecules/SaveRecording.tsx +++ b/src/components/molecules/SaveRecording.tsx @@ -97,7 +97,7 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { ? ( @@ -105,7 +105,7 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { ) : } {waitingForSave && From eb0b58befcc872569b9ffde3f64210f31cda9025 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 00:15:25 +0530 Subject: [PATCH 101/238] feat: add chinese translation for browser recording save --- public/locales/zh.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index 01bf8e5da..09840b6f5 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -154,7 +154,8 @@ "confirm_pagination": "确认分页", "confirm_limit": "确认限制", "finish_capture": "完成捕获", - "finish": "完成" + "finish": "完成", + "cancel": "取消" }, "screenshot": { "capture_fullpage": "捕获整页", @@ -212,5 +213,13 @@ "tooltips": { "saving": "正在优化并保存工作流程" } + }, + "browser_recording": { + "modal": { + "confirm_discard": "您确定要放弃录制吗?" + }, + "notifications": { + "terminated": "当前录制已终止" + } } } \ No newline at end of file From bda5d6f001337f99b724d873aa5a0bb846499ee8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 00:16:02 +0530 Subject: [PATCH 102/238] feat: add german translation for browser recording save --- public/locales/de.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/public/locales/de.json b/public/locales/de.json index 5148b2d2c..1ade8e2a6 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -153,7 +153,8 @@ "confirm_pagination": "Paginierung bestätigen", "confirm_limit": "Limit bestätigen", "finish_capture": "Erfassung abschließen", - "finish": "Fertig" + "finish": "Fertig", + "cancel": "Abbrechen" }, "screenshot": { "capture_fullpage": "Vollständige Seite erfassen", @@ -211,5 +212,13 @@ "tooltips": { "saving": "Workflow wird optimiert und gespeichert" } + }, + "browser_recording": { + "modal": { + "confirm_discard": "Sind Sie sicher, dass Sie die Aufnahme verwerfen möchten?" + }, + "notifications": { + "terminated": "Aktuelle Aufnahme wurde beendet" + } } } From f1b028d2d79267ca586faa708707e0bc6ff14e25 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 00:16:38 +0530 Subject: [PATCH 103/238] feat: add spanish translation for browser recording save --- public/locales/es.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/public/locales/es.json b/public/locales/es.json index 5a42b4317..fb68ef015 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -154,7 +154,8 @@ "confirm_pagination": "Confirmar Paginación", "confirm_limit": "Confirmar Límite", "finish_capture": "Finalizar Captura", - "finish": "Finalizar" + "finish": "Finalizar", + "cancel": "Cancelar" }, "screenshot": { "capture_fullpage": "Capturar Página Completa", @@ -212,5 +213,13 @@ "tooltips": { "saving": "Optimizando y guardando el flujo de trabajo" } - } + }, + "browser_recording": { + "modal": { + "confirm_discard": "¿Está seguro de que desea descartar la grabación?" + }, + "notifications": { + "terminated": "La grabación actual fue terminada" + } + } } \ No newline at end of file From 0870e51d27a587a18efaf7684d796a05dec3cf70 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 00:16:55 +0530 Subject: [PATCH 104/238] feat: add japanese translation for browser recording save --- public/locales/ja.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/public/locales/ja.json b/public/locales/ja.json index 46a75b154..0202160fd 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -154,7 +154,8 @@ "confirm_pagination": "ページネーションを確認", "confirm_limit": "制限を確認", "finish_capture": "取得を完了", - "finish": "完了" + "finish": "完了", + "cancel": "キャンセル" }, "screenshot": { "capture_fullpage": "フルページを取得", @@ -212,5 +213,13 @@ "tooltips": { "saving": "ワークフローを最適化して保存中" } + }, + "browser_recording": { + "modal": { + "confirm_discard": "録画を破棄してもよろしいですか?" + }, + "notifications": { + "terminated": "現在の録画は終了しました" + } } } From 586f1c16c2320fe6699d0d2c4b9b1444a4ece49f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 00:17:14 +0530 Subject: [PATCH 105/238] feat: add english translation for browser recording save --- public/locales/en.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/public/locales/en.json b/public/locales/en.json index 3a65f8988..4b8560086 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -156,7 +156,8 @@ "confirm_pagination": "Confirm Pagination", "confirm_limit": "Confirm Limit", "finish_capture": "Finish Capture", - "finish": "Finish" + "finish": "Finish", + "cancel": "Cancel" }, "screenshot": { "capture_fullpage": "Capture Fullpage", @@ -214,5 +215,13 @@ "tooltips": { "saving": "Optimizing and saving the workflow" } + }, + "browser_recording": { + "modal": { + "confirm_discard": "Are you sure you want to discard the recording?" + }, + "notifications": { + "terminated": "Current Recording was terminated" + } } } \ No newline at end of file From a614d067e103ff14e8ff1a738c2b26679ac0efc1 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 00:17:48 +0530 Subject: [PATCH 106/238] feat: add translation for browser recording save --- .../molecules/BrowserRecordingSave.tsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/molecules/BrowserRecordingSave.tsx b/src/components/molecules/BrowserRecordingSave.tsx index 03758717c..e1eff20e6 100644 --- a/src/components/molecules/BrowserRecordingSave.tsx +++ b/src/components/molecules/BrowserRecordingSave.tsx @@ -5,8 +5,10 @@ import { useGlobalInfoStore } from '../../context/globalInfo'; import { stopRecording } from "../../api/recording"; import { useNavigate } from 'react-router-dom'; import { GenericModal } from "../atoms/GenericModal"; +import { useTranslation } from 'react-i18next'; const BrowserRecordingSave = () => { + const { t } = useTranslation(); const [openModal, setOpenModal] = useState(false); const { recordingName, browserId, setBrowserId, notify } = useGlobalInfoStore(); const navigate = useNavigate(); @@ -14,7 +16,7 @@ const BrowserRecordingSave = () => { const goToMainMenu = async () => { if (browserId) { await stopRecording(browserId); - notify('warning', 'Current Recording was terminated'); + notify('warning', t('browser_recording.notifications.terminated')); setBrowserId(null); } navigate('/'); @@ -25,30 +27,29 @@ const BrowserRecordingSave = () => {
setOpenModal(false)} modalStyle={modalStyle}> - Are you sure you want to discard the recording? + {t('browser_recording.modal.confirm_discard')} @@ -60,7 +61,7 @@ const BrowserRecordingSave = () => { ); } -export default BrowserRecordingSave +export default BrowserRecordingSave; const modalStyle = { top: '25%', From 8b8a4d95e326906e8db1882282ebfe33236b831b Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:30:34 +0530 Subject: [PATCH 107/238] feat: add chinese translation for interpretation log --- public/locales/zh.json | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index 09840b6f5..ce4adc798 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -216,10 +216,28 @@ }, "browser_recording": { "modal": { - "confirm_discard": "您确定要放弃录制吗?" + "confirm_discard": "您确定要放弃录制吗?" }, "notifications": { - "terminated": "当前录制已终止" + "terminated": "当前录制已终止" + } + }, + "interpretation_log": { + "titles": { + "output_preview": "输出数据预览", + "screenshot": "截图" + }, + "messages": { + "additional_rows": "完成录制后将提取更多数据行。", + "successful_training": "您已成功训练机器人执行操作!点击下方按钮预览机器人将提取的数据。", + "no_selection": "看起来您还没有选择要提取的内容。选择后,机器人将在此处显示您的选择预览。" + }, + "data_sections": { + "binary_received": "---------- 已接收二进制输出数据 ----------", + "serializable_received": "---------- 已接收可序列化输出数据 ----------", + "mimetype": "MIME类型:", + "image_below": "图片显示如下:", + "separator": "--------------------------------------------------" } } } \ No newline at end of file From 2c5f4f1afcaaf47b208d54ecd5b1981966b0a360 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:30:56 +0530 Subject: [PATCH 108/238] feat: add german translation for interpretation log --- public/locales/de.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 1ade8e2a6..6ef44428e 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -220,5 +220,23 @@ "notifications": { "terminated": "Aktuelle Aufnahme wurde beendet" } + }, + "interpretation_log": { + "titles": { + "output_preview": "Vorschau der Ausgabedaten", + "screenshot": "Bildschirmfoto" + }, + "messages": { + "additional_rows": "Weitere Datenzeilen werden nach Abschluss der Aufnahme extrahiert.", + "successful_training": "Sie haben den Roboter erfolgreich für Aktionen trainiert! Klicken Sie auf die Schaltfläche unten, um eine Vorschau der Daten zu erhalten, die Ihr Roboter extrahieren wird.", + "no_selection": "Sie haben noch nichts zur Extraktion ausgewählt. Sobald Sie dies tun, wird der Roboter hier eine Vorschau Ihrer Auswahl anzeigen." + }, + "data_sections": { + "binary_received": "---------- Binäre Ausgabedaten empfangen ----------", + "serializable_received": "---------- Serialisierbare Ausgabedaten empfangen ----------", + "mimetype": "Medientyp: ", + "image_below": "Bild wird unten angezeigt:", + "separator": "--------------------------------------------------" + } } } From e65b1d57c28a4b3dde0725732be80884e4804b8d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:31:11 +0530 Subject: [PATCH 109/238] feat: add spanish translation for interpretation log --- public/locales/es.json | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/public/locales/es.json b/public/locales/es.json index fb68ef015..79b560dd1 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -216,10 +216,28 @@ }, "browser_recording": { "modal": { - "confirm_discard": "¿Está seguro de que desea descartar la grabación?" + "confirm_discard": "¿Está seguro de que desea descartar la grabación?" }, "notifications": { - "terminated": "La grabación actual fue terminada" + "terminated": "La grabación actual fue terminada" } - } + }, + "interpretation_log": { + "titles": { + "output_preview": "Vista Previa de Datos de Salida", + "screenshot": "Captura de pantalla" + }, + "messages": { + "additional_rows": "Se extraerán filas adicionales de datos una vez que termine la grabación.", + "successful_training": "¡Has entrenado exitosamente al robot para realizar acciones! Haz clic en el botón de abajo para obtener una vista previa de los datos que tu robot extraerá.", + "no_selection": "Parece que aún no has seleccionado nada para extraer. Una vez que lo hagas, el robot mostrará una vista previa de tus selecciones aquí." + }, + "data_sections": { + "binary_received": "---------- Datos binarios de salida recibidos ----------", + "serializable_received": "---------- Datos serializables de salida recibidos ----------", + "mimetype": "tipo MIME: ", + "image_below": "La imagen se muestra a continuación:", + "separator": "--------------------------------------------------" + } + } } \ No newline at end of file From 2cf6b2c8c6149d2c18aae3e9d5d049c106e2e615 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:31:33 +0530 Subject: [PATCH 110/238] feat: add japanese translation for interpretation log --- public/locales/ja.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 0202160fd..0de2aa7c4 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -221,5 +221,23 @@ "notifications": { "terminated": "現在の録画は終了しました" } + }, + "interpretation_log": { + "titles": { + "output_preview": "出力データプレビュー", + "screenshot": "スクリーンショット" + }, + "messages": { + "additional_rows": "記録が完了すると、追加のデータ行が抽出されます。", + "successful_training": "ロボットのアクショントレーニングが成功しました!下のボタンをクリックすると、ロボットが抽出するデータのプレビューが表示されます。", + "no_selection": "まだ抽出対象が選択されていません。選択すると、ロボットがここで選択内容のプレビューを表示します。" + }, + "data_sections": { + "binary_received": "---------- バイナリ出力データを受信 ----------", + "serializable_received": "---------- シリアライズ可能な出力データを受信 ----------", + "mimetype": "MIMEタイプ: ", + "image_below": "画像は以下に表示されます:", + "separator": "--------------------------------------------------" + } } } From 2d35f29aea8d4df7073d513784df0c24145f62e7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:31:49 +0530 Subject: [PATCH 111/238] feat: add english translation for interpretation log --- public/locales/en.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 4b8560086..abc060821 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -223,5 +223,23 @@ "notifications": { "terminated": "Current Recording was terminated" } + }, + "interpretation_log": { + "titles": { + "output_preview": "Output Data Preview", + "screenshot": "Screenshot" + }, + "messages": { + "additional_rows": "Additional rows of data will be extracted once you finish recording.", + "successful_training": "You've successfully trained the robot to perform actions! Click on the button below to get a preview of the data your robot will extract.", + "no_selection": "It looks like you have not selected anything for extraction yet. Once you do, the robot will show a preview of your selections here." + }, + "data_sections": { + "binary_received": "---------- Binary output data received ----------", + "serializable_received": "---------- Serializable output data received ----------", + "mimetype": "mimetype: ", + "image_below": "Image is rendered below:", + "separator": "--------------------------------------------------" + } } } \ No newline at end of file From c367af3bc432a22c6b5988e3aa3a03e8ee773d68 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:32:08 +0530 Subject: [PATCH 112/238] feat: add translation for interpretation log --- .../molecules/InterpretationLog.tsx | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/components/molecules/InterpretationLog.tsx b/src/components/molecules/InterpretationLog.tsx index 24ba848b4..0a7715353 100644 --- a/src/components/molecules/InterpretationLog.tsx +++ b/src/components/molecules/InterpretationLog.tsx @@ -17,6 +17,7 @@ import StorageIcon from '@mui/icons-material/Storage'; import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; import { SidePanelHeader } from './SidePanelHeader'; import { useGlobalInfoStore } from '../../context/globalInfo'; +import { useTranslation } from 'react-i18next'; interface InterpretationLogProps { isOpen: boolean; @@ -24,6 +25,7 @@ interface InterpretationLogProps { } export const InterpretationLog: React.FC = ({ isOpen, setIsOpen }) => { + const { t } = useTranslation(); const [log, setLog] = useState(''); const [customValue, setCustomValue] = useState(''); const [tableData, setTableData] = useState([]); @@ -63,28 +65,29 @@ export const InterpretationLog: React.FC = ({ isOpen, se const handleSerializableCallback = useCallback((data: any) => { setLog((prevState) => - prevState + '\n' + '---------- Serializable output data received ----------' + '\n' - + JSON.stringify(data, null, 2) + '\n' + '--------------------------------------------------'); + prevState + '\n' + t('interpretation_log.data_sections.serializable_received') + '\n' + + JSON.stringify(data, null, 2) + '\n' + t('interpretation_log.data_sections.separator')); if (Array.isArray(data)) { setTableData(data); } scrollLogToBottom(); - }, [log, scrollLogToBottom]); + }, [log, scrollLogToBottom, t]); const handleBinaryCallback = useCallback(({ data, mimetype }: any) => { const base64String = Buffer.from(data).toString('base64'); const imageSrc = `data:${mimetype};base64,${base64String}`; setLog((prevState) => - prevState + '\n' + '---------- Binary output data received ----------' + '\n' - + `mimetype: ${mimetype}` + '\n' + 'Image is rendered below:' + '\n' - + '------------------------------------------------'); + prevState + '\n' + t('interpretation_log.data_sections.binary_received') + '\n' + + t('interpretation_log.data_sections.mimetype') + mimetype + '\n' + + t('interpretation_log.data_sections.image_below') + '\n' + + t('interpretation_log.data_sections.separator')); setBinaryData(imageSrc); scrollLogToBottom(); - }, [log, scrollLogToBottom]); + }, [log, scrollLogToBottom, t]); const handleCustomValueChange = (event: React.ChangeEvent) => { @@ -136,7 +139,8 @@ export const InterpretationLog: React.FC = ({ isOpen, se }, }} > - Output Data Preview + + {t('interpretation_log.titles.output_preview')} = ({ isOpen, se }, }} > - - Output Data Preview - + + + {t('interpretation_log.titles.output_preview')} +
= ({ isOpen, se { binaryData ? (
- Screenshot - Binary Output + + {t('interpretation_log.titles.screenshot')} + + {t('interpretation_log.titles.screenshot')}
) : tableData.length > 0 ? ( <> @@ -193,7 +200,9 @@ export const InterpretationLog: React.FC = ({ isOpen, se
- Additional rows of data will be extracted once you finish recording. + + {t('interpretation_log.messages.additional_rows')} + ) : ( @@ -201,13 +210,13 @@ export const InterpretationLog: React.FC = ({ isOpen, se {hasScrapeListAction || hasScrapeSchemaAction || hasScreenshotAction ? ( <> - You've successfully trained the robot to perform actions! Click on the button below to get a preview of the data your robot will extract. + {t('interpretation_log.messages.successful_training')} ) : ( - It looks like you have not selected anything for extraction yet. Once you do, the robot will show a preview of your selections here. + {t('interpretation_log.messages.no_selection')} )} @@ -219,4 +228,4 @@ export const InterpretationLog: React.FC = ({ isOpen, se ); -} \ No newline at end of file +}; \ No newline at end of file From 14d8940ac4430a5e54036f70b37275c064a111c7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:41:20 +0530 Subject: [PATCH 113/238] feat: add english translation for interpretation buttons --- public/locales/en.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index abc060821..b5bffd420 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -241,5 +241,23 @@ "image_below": "Image is rendered below:", "separator": "--------------------------------------------------" } + }, + "interpretation_buttons": { + "buttons": { + "preview": "Get Preview of Output Data", + "yes": "Yes", + "no": "No" + }, + "messages": { + "extracting": "Extracting data...please wait for 10secs to 1min", + "restart_required": "Please restart the interpretation after updating the recording", + "run_finished": "Run finished", + "run_failed": "Run failed to start" + }, + "modal": { + "use_previous": "Do you want to use your previous selection as a condition for performing this action?", + "previous_action": "Your previous action was: ", + "element_text": "on an element with text " + } } } \ No newline at end of file From 395874e50a3036d281c129a3941e17349bf4c7a1 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:41:46 +0530 Subject: [PATCH 114/238] feat: add japanese translation for interpretation buttons --- public/locales/ja.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 0de2aa7c4..274a8d065 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -239,5 +239,23 @@ "image_below": "画像は以下に表示されます:", "separator": "--------------------------------------------------" } + }, + "interpretation_buttons": { + "buttons": { + "preview": "出力データのプレビューを取得", + "yes": "はい", + "no": "いいえ" + }, + "messages": { + "extracting": "データ抽出中...10秒から1分ほどお待ちください", + "restart_required": "録画を更新した後、解釈を再起動してください", + "run_finished": "実行完了", + "run_failed": "実行の開始に失敗しました" + }, + "modal": { + "use_previous": "この操作の条件として前回の選択を使用しますか?", + "previous_action": "前回の操作: ", + "element_text": "テキスト要素 " + } } } From 6956e42ff0cc7b4507b9bedee65f48ed483364da Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:42:03 +0530 Subject: [PATCH 115/238] feat: add spanish translation for interpretation buttons --- public/locales/es.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 79b560dd1..f1f744eda 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -239,5 +239,23 @@ "image_below": "La imagen se muestra a continuación:", "separator": "--------------------------------------------------" } + }, + "interpretation_buttons": { + "buttons": { + "preview": "Obtener Vista Previa de Datos de Salida", + "yes": "Sí", + "no": "No" + }, + "messages": { + "extracting": "Extrayendo datos...espere de 10 segundos a 1 minuto", + "restart_required": "Por favor, reinicie la interpretación después de actualizar la grabación", + "run_finished": "Ejecución finalizada", + "run_failed": "Error al iniciar la ejecución" + }, + "modal": { + "use_previous": "¿Desea usar su selección anterior como condición para realizar esta acción?", + "previous_action": "Su acción anterior fue: ", + "element_text": "en un elemento con texto " + } } } \ No newline at end of file From 3d584f150257ee34b21bd58ddf30623524938c4a Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:42:18 +0530 Subject: [PATCH 116/238] feat: add german translation for interpretation buttons --- public/locales/de.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 6ef44428e..697473f25 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -238,5 +238,23 @@ "image_below": "Bild wird unten angezeigt:", "separator": "--------------------------------------------------" } + }, + "interpretation_buttons": { + "buttons": { + "preview": "Vorschau der Ausgabedaten anzeigen", + "yes": "Ja", + "no": "Nein" + }, + "messages": { + "extracting": "Daten werden extrahiert...bitte warten Sie 10 Sekunden bis 1 Minute", + "restart_required": "Bitte starten Sie die Interpretation nach der Aktualisierung der Aufnahme neu", + "run_finished": "Durchlauf beendet", + "run_failed": "Start fehlgeschlagen" + }, + "modal": { + "use_previous": "Möchten Sie Ihre vorherige Auswahl als Bedingung für diese Aktion verwenden?", + "previous_action": "Ihre vorherige Aktion war: ", + "element_text": "auf einem Element mit Text " + } } } From aacb5153d48d769a92fa1bb5005a98bd6c4813b9 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:42:34 +0530 Subject: [PATCH 117/238] feat: add chinese translation for interpretation buttons --- public/locales/zh.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index ce4adc798..c31d83cc6 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -239,5 +239,23 @@ "image_below": "图片显示如下:", "separator": "--------------------------------------------------" } + }, + "interpretation_buttons": { + "buttons": { + "preview": "获取输出数据预览", + "yes": "是", + "no": "否" + }, + "messages": { + "extracting": "正在提取数据...请等待10秒到1分钟", + "restart_required": "更新录制后请重新启动解释", + "run_finished": "运行完成", + "run_failed": "运行启动失败" + }, + "modal": { + "use_previous": "您要将之前的选择用作执行此操作的条件吗?", + "previous_action": "您之前的操作是:", + "element_text": "在文本元素上 " + } } } \ No newline at end of file From 6a4bb3ed209a22306a6b230dc0f4ed60ceee537c Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:42:59 +0530 Subject: [PATCH 118/238] feat: add translation for interpretation buttons --- .../molecules/InterpretationButtons.tsx | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/components/molecules/InterpretationButtons.tsx b/src/components/molecules/InterpretationButtons.tsx index 9d9837611..624a57b4c 100644 --- a/src/components/molecules/InterpretationButtons.tsx +++ b/src/components/molecules/InterpretationButtons.tsx @@ -7,6 +7,7 @@ import { useGlobalInfoStore } from "../../context/globalInfo"; import { GenericModal } from "../atoms/GenericModal"; import { WhereWhatPair } from "maxun-core"; import HelpIcon from '@mui/icons-material/Help'; +import { useTranslation } from "react-i18next"; interface InterpretationButtonsProps { enableStepping: (isPaused: boolean) => void; @@ -23,6 +24,7 @@ const interpretationInfo: InterpretationInfo = { }; export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsProps) => { + const { t } = useTranslation(); const [info, setInfo] = useState(interpretationInfo); const [decisionModal, setDecisionModal] = useState<{ pair: WhereWhatPair | null, @@ -44,9 +46,9 @@ export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsP const breakpointHitHandler = useCallback(() => { setInfo({ running: false, isPaused: true }); - notify('warning', 'Please restart the interpretation after updating the recording'); + notify('warning', t('interpretation_buttons.messages.restart_required')); enableStepping(true); - }, [enableStepping]); + }, [enableStepping, t]); const decisionHandler = useCallback( ({ pair, actionType, lastData }: { pair: WhereWhatPair | null, actionType: string, lastData: { selector: string, action: string, tagName: string, innerText: string } }) => { @@ -73,11 +75,12 @@ export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsP return ( <> - Do you want to use your previous selection as a condition for performing this action? + {t('interpretation_buttons.modal.use_previous')} - Your previous action was: {decisionModal.action}, on an element with text {decisionModal.innerText} + {t('interpretation_buttons.modal.previous_action')} {decisionModal.action}, + {t('interpretation_buttons.modal.element_text')} {decisionModal.innerText} @@ -105,9 +108,9 @@ export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsP const finished = await interpretCurrentRecording(); setInfo({ ...info, running: false }); if (finished) { - notify('info', 'Run finished'); + notify('info', t('interpretation_buttons.messages.run_finished')); } else { - notify('error', 'Run failed to start'); + notify('error', t('interpretation_buttons.messages.run_failed')); } } }; @@ -139,9 +142,12 @@ export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsP disabled={info.running} sx={{ display: 'grid' }} > - {info.running ? - Extracting data...please wait for 10secs to 1min - : 'Get Preview of Output Data'} + {info.running ? ( + + + {t('interpretation_buttons.messages.extracting')} + + ) : t('interpretation_buttons.buttons.preview')} { }} @@ -166,8 +172,12 @@ export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsP {handleDescription()}
- - + +
From a7d415dcda3bc28350e4e63917fcba05002b57fc Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:54:22 +0530 Subject: [PATCH 119/238] feat: add chinese translation for recording page --- public/locales/zh.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index c31d83cc6..65aa0856d 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -257,5 +257,10 @@ "previous_action": "您之前的操作是:", "element_text": "在文本元素上 " } + }, + "recording_page": { + "loader": { + "browser_startup": "正在启动浏览器...正在导航至{{url}}" + } } } \ No newline at end of file From 9cb85192f1076d914ef52f8a7a8485d867a507a4 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:54:41 +0530 Subject: [PATCH 120/238] feat: add german translation for recording page --- public/locales/de.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 697473f25..c796f2dcd 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -256,5 +256,10 @@ "previous_action": "Ihre vorherige Aktion war: ", "element_text": "auf einem Element mit Text " } + }, + "recording_page": { + "loader": { + "browser_startup": "Browser wird gestartet...Navigation zu {{url}}" + } } } From e9c4ea0d2eb849ca5b8d1c06290a2c3e240cac8d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:54:56 +0530 Subject: [PATCH 121/238] feat: add spanish translation for recording page --- public/locales/es.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index f1f744eda..8111e104e 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -257,5 +257,10 @@ "previous_action": "Su acción anterior fue: ", "element_text": "en un elemento con texto " } + }, + "recording_page": { + "loader": { + "browser_startup": "Iniciando el navegador...Navegando a {{url}}" + } } } \ No newline at end of file From 05c6494b079152e7ec25d3868cf6264e4acb8af1 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:55:11 +0530 Subject: [PATCH 122/238] feat: add japanese translation for recording page --- public/locales/ja.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 274a8d065..c9ce883c0 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -257,5 +257,10 @@ "previous_action": "前回の操作: ", "element_text": "テキスト要素 " } + }, + "recording_page": { + "loader": { + "browser_startup": "ブラウザを起動中...{{url}}に移動中" + } } } From c77807c1369f3c06e46f311de8f5cf3d0d9b5a45 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:55:25 +0530 Subject: [PATCH 123/238] feat: add english translation for recording page --- public/locales/en.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index b5bffd420..ec51d1f91 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -259,5 +259,10 @@ "previous_action": "Your previous action was: ", "element_text": "on an element with text " } + }, + "recording_page": { + "loader": { + "browser_startup": "Spinning up a browser...Navigating to {{url}}" + } } } \ No newline at end of file From cf2fe717fdd4828330c16f5d521ae6635cb6048b Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 12:55:44 +0530 Subject: [PATCH 124/238] feat: add translation for recording page --- src/pages/RecordingPage.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/RecordingPage.tsx b/src/pages/RecordingPage.tsx index 18fad49f4..82fa7e320 100644 --- a/src/pages/RecordingPage.tsx +++ b/src/pages/RecordingPage.tsx @@ -15,6 +15,7 @@ import { editRecordingFromStorage } from "../api/storage"; import { WhereWhatPair } from "maxun-core"; import styled from "styled-components"; import BrowserRecordingSave from '../components/molecules/BrowserRecordingSave'; +import { useTranslation } from 'react-i18next'; interface RecordingPageProps { recordingName?: string; @@ -26,7 +27,7 @@ export interface PairForEdit { } export const RecordingPage = ({ recordingName }: RecordingPageProps) => { - + const { t } = useTranslation(); const [isLoaded, setIsLoaded] = React.useState(false); const [hasScrollbar, setHasScrollbar] = React.useState(false); const [pairForEdit, setPairForEdit] = useState({ @@ -145,7 +146,7 @@ export const RecordingPage = ({ recordingName }: RecordingPageProps) => { ) : ( - + )} From 1f86a408b7bfc0e6ba4d56f342d60a22b157bff0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:08:44 +0530 Subject: [PATCH 125/238] feat: add english translation for integration settings --- public/locales/en.json | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index ec51d1f91..322d21ca9 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -264,5 +264,40 @@ "loader": { "browser_startup": "Spinning up a browser...Navigating to {{url}}" } + }, + "integration_settings": { + "title": "Integrate with Google Sheet", + "descriptions": { + "sync_info": "If you enable this option, every time this robot runs a task successfully, its captured data will be appended to your Google Sheet.", + "authenticated_as": "Authenticated as: {{email}}" + }, + "alerts": { + "success": { + "title": "Google Sheet Integrated Successfully.", + "content": "Every time this robot creates a successful run, its captured data is appended to your {{sheetName}} Google Sheet. You can check the data updates", + "here": "here", + "note": "Note:", + "sync_limitation": "The data extracted before integrating with Google Sheets will not be synced in the Google Sheet. Only the data extracted after the integration will be synced." + } + }, + "buttons": { + "authenticate": "Authenticate with Google", + "fetch_sheets": "Fetch Google Spreadsheets", + "remove_integration": "Remove Integration", + "submit": "Submit" + }, + "fields": { + "select_sheet": "Select Google Sheet", + "selected_sheet": "Selected Sheet: {{name}} (ID: {{id}})" + }, + "errors": { + "auth_error": "Error authenticating with Google", + "fetch_error": "Error fetching spreadsheet files: {{message}}", + "update_error": "Error updating Google Sheet ID: {{message}}", + "remove_error": "Error removing Google Sheets integration: {{message}}" + }, + "notifications": { + "sheet_selected": "Google Sheet selected successfully" + } } } \ No newline at end of file From 7733e62c297972440ac011f1d192234813fced56 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:09:00 +0530 Subject: [PATCH 126/238] feat: add japanese translation for integration settings --- public/locales/ja.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index c9ce883c0..a93cae72c 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -262,5 +262,31 @@ "loader": { "browser_startup": "ブラウザを起動中...{{url}}に移動中" } + }, + "integration_settings": { + "title": "Google Sheetと連携", + "descriptions": { + "sync_info": "このオプションを有効にすると、このロボットがタスクを正常に実行するたびに、取得したデータがGoogle Sheetに追加されます。", + "authenticated_as": "認証済みユーザー: {{email}}" + }, + "alerts": { + "success": { + "title": "Google Sheetの連携が完了しました。", + "content": "このロボットが正常に実行を完了するたびに、取得したデータはGoogle Sheet {{sheetName}}に追加されます。データの更新は", + "here": "こちら", + "note": "注意:", + "sync_limitation": "Google Sheetsとの連携前に抽出されたデータは同期されません。連携後に抽出されたデータのみが同期されます。" + } + }, + "buttons": { + "authenticate": "Googleで認証", + "fetch_sheets": "Google Sheetsを取得", + "remove_integration": "連携を解除", + "submit": "送信" + }, + "fields": { + "select_sheet": "Google Sheetを選択", + "selected_sheet": "選択したシート: {{name}} (ID: {{id}})" + } } } From 1eb4bc6b032c8afadc03e21f120b3d242027b037 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:09:18 +0530 Subject: [PATCH 127/238] feat: add spanish translation for integration settings --- public/locales/es.json | 46 +++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/public/locales/es.json b/public/locales/es.json index 8111e104e..e38ba1c7b 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -242,25 +242,51 @@ }, "interpretation_buttons": { "buttons": { - "preview": "Obtener Vista Previa de Datos de Salida", - "yes": "Sí", - "no": "No" + "preview": "Obtener Vista Previa de Datos de Salida", + "yes": "Sí", + "no": "No" }, "messages": { - "extracting": "Extrayendo datos...espere de 10 segundos a 1 minuto", - "restart_required": "Por favor, reinicie la interpretación después de actualizar la grabación", - "run_finished": "Ejecución finalizada", - "run_failed": "Error al iniciar la ejecución" + "extracting": "Extrayendo datos...espere de 10 segundos a 1 minuto", + "restart_required": "Por favor, reinicie la interpretación después de actualizar la grabación", + "run_finished": "Ejecución finalizada", + "run_failed": "Error al iniciar la ejecución" }, "modal": { - "use_previous": "¿Desea usar su selección anterior como condición para realizar esta acción?", - "previous_action": "Su acción anterior fue: ", - "element_text": "en un elemento con texto " + "use_previous": "¿Desea usar su selección anterior como condición para realizar esta acción?", + "previous_action": "Su acción anterior fue: ", + "element_text": "en un elemento con texto " } }, "recording_page": { "loader": { "browser_startup": "Iniciando el navegador...Navegando a {{url}}" } + }, + "integration_settings": { + "title": "Integrar con Google Sheet", + "descriptions": { + "sync_info": "Si habilitas esta opción, cada vez que este robot ejecute una tarea exitosamente, sus datos capturados se añadirán a tu Google Sheet.", + "authenticated_as": "Autenticado como: {{email}}" + }, + "alerts": { + "success": { + "title": "Google Sheet integrado exitosamente.", + "content": "Cada vez que este robot crea una ejecución exitosa, sus datos capturados se añaden a tu Google Sheet {{sheetName}}. Puedes verificar las actualizaciones de datos", + "here": "aquí", + "note": "Nota:", + "sync_limitation": "Los datos extraídos antes de la integración con Google Sheets no se sincronizarán en el Google Sheet. Solo se sincronizarán los datos extraídos después de la integración." + } + }, + "buttons": { + "authenticate": "Autenticar con Google", + "fetch_sheets": "Obtener Google Sheets", + "remove_integration": "Eliminar integración", + "submit": "Enviar" + }, + "fields": { + "select_sheet": "Seleccionar Google Sheet", + "selected_sheet": "Hoja seleccionada: {{name}} (ID: {{id}})" + } } } \ No newline at end of file From 71b60eea63fe6a16964607e75e425f79efe65998 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:09:38 +0530 Subject: [PATCH 128/238] feat: add german translation for integration settings --- public/locales/de.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index c796f2dcd..0e8b5832f 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -261,5 +261,31 @@ "loader": { "browser_startup": "Browser wird gestartet...Navigation zu {{url}}" } + }, + "integration_settings": { + "title": "Mit Google Sheet integrieren", + "descriptions": { + "sync_info": "Wenn Sie diese Option aktivieren, werden bei jeder erfolgreichen Ausführung dieses Roboters die erfassten Daten in Ihrem Google Sheet ergänzt.", + "authenticated_as": "Authentifiziert als: {{email}}" + }, + "alerts": { + "success": { + "title": "Google Sheet erfolgreich integriert.", + "content": "Jedes Mal, wenn dieser Roboter eine erfolgreiche Ausführung erstellt, werden die erfassten Daten Ihrem Google Sheet {{sheetName}} hinzugefügt. Sie können die Datenaktualisierungen", + "here": "hier", + "note": "Hinweis:", + "sync_limitation": "Die vor der Integration mit Google Sheets extrahierten Daten werden nicht im Google Sheet synchronisiert. Nur die nach der Integration extrahierten Daten werden synchronisiert." + } + }, + "buttons": { + "authenticate": "Mit Google authentifizieren", + "fetch_sheets": "Google Sheets abrufen", + "remove_integration": "Integration entfernen", + "submit": "Absenden" + }, + "fields": { + "select_sheet": "Google Sheet auswählen", + "selected_sheet": "Ausgewähltes Sheet: {{name}} (ID: {{id}})" + } } } From fbf71028e93934828dcbb34fdc5b6e60391c82c0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:09:57 +0530 Subject: [PATCH 129/238] feat: add chinese translation for integration settings --- public/locales/zh.json | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 65aa0856d..df45c45c9 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -262,5 +262,31 @@ "loader": { "browser_startup": "正在启动浏览器...正在导航至{{url}}" } + }, + "integration_settings": { + "title": "与Google Sheet集成", + "descriptions": { + "sync_info": "如果启用此选项,每次机器人成功运行任务时,捕获的数据都会追加到您的Google Sheet中。", + "authenticated_as": "已验证身份: {{email}}" + }, + "alerts": { + "success": { + "title": "Google Sheet集成成功。", + "content": "每次此机器人创建成功运行时,捕获的数据都会追加到您的Google Sheet {{sheetName}}中。您可以查看数据更新", + "here": "在此处", + "note": "注意:", + "sync_limitation": "与Google Sheets集成之前提取的数据将不会同步到Google Sheet中。只有集成后提取的数据才会同步。" + } + }, + "buttons": { + "authenticate": "使用Google验证", + "fetch_sheets": "获取Google Sheets", + "remove_integration": "移除集成", + "submit": "提交" + }, + "fields": { + "select_sheet": "选择Google Sheet", + "selected_sheet": "已选择表格: {{name}} (ID: {{id}})" + } } } \ No newline at end of file From 0a55388e525044c7c7500b63d6b4c27b64e701ee Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:10:38 +0530 Subject: [PATCH 130/238] feat: add translation for integration settings --- .../molecules/IntegrationSettings.tsx | 65 ++++++++----------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/src/components/molecules/IntegrationSettings.tsx b/src/components/molecules/IntegrationSettings.tsx index b34bc0e92..97973645f 100644 --- a/src/components/molecules/IntegrationSettings.tsx +++ b/src/components/molecules/IntegrationSettings.tsx @@ -15,6 +15,7 @@ import { useGlobalInfoStore } from "../../context/globalInfo"; import { getStoredRecording } from "../../api/storage"; import { apiUrl } from "../../apiConfig.js"; import Cookies from 'js-cookie'; +import { useTranslation } from "react-i18next"; interface IntegrationProps { isOpen: boolean; @@ -33,6 +34,7 @@ export const IntegrationSettingsModal = ({ handleStart, handleClose, }: IntegrationProps) => { + const { t } = useTranslation(); const [settings, setSettings] = useState({ spreadsheetId: "", spreadsheetName: "", @@ -168,38 +170,28 @@ export const IntegrationSettingsModal = ({ return ( -
+ }}> - Integrate with Google Sheet{" "} - {/* */} + {t('integration_settings.title')} {recording && recording.google_sheet_id ? ( <> - Google Sheet Integrated Successfully. - Every time this robot creates a successful run, its captured data - is appended to your {recording.google_sheet_name} Google Sheet. - You can check the data updates{" "} - {t('integration_settings.alerts.success.title')} + {t('integration_settings.alerts.success.content', { sheetName: recording.google_sheet_name })} + - here - - . + rel="noreferrer"> + {t('integration_settings.alerts.success.here')} + .
- Note: The data extracted before integrating with - Google Sheets will not be synced in the Google Sheet. Only the - data extracted after the integration will be synced. + {t('integration_settings.alerts.success.note')} {t('integration_settings.alerts.success.sync_limitation')}
) : ( <> {!recording?.google_sheet_email ? ( <> -

- If you enable this option, every time this robot runs a task - successfully, its captured data will be appended to your - Google Sheet. -

+

{t('integration_settings.descriptions.sync_info')}

) : ( <> {recording.google_sheet_email && ( - Authenticated as: {recording.google_sheet_email} + {t('integration_settings.descriptions.authenticated_as', { + email: recording.google_sheet_email + })} )} @@ -247,14 +237,14 @@ export const IntegrationSettingsModal = ({ color="primary" onClick={fetchSpreadsheetFiles} > - Fetch Google Spreadsheets + {t('integration_settings.buttons.fetch_sheets')}
@@ -263,7 +253,7 @@ export const IntegrationSettingsModal = ({ - Selected Sheet:{" "} - { - spreadsheets.find( - (s) => s.id === settings.spreadsheetId - )?.name - }{" "} - (ID: {settings.spreadsheetId}) + {t('integration_settings.fields.selected_sheet', { + name: spreadsheets.find((s) => s.id === settings.spreadsheetId)?.name, + id: settings.spreadsheetId + })} )} @@ -298,7 +285,7 @@ export const IntegrationSettingsModal = ({ style={{ marginTop: "10px" }} disabled={!settings.spreadsheetId || loading} > - Submit + {t('integration_settings.buttons.submit')} )} From 681abac471ea1015f0c88ec193bbfee0f99085a6 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:33:07 +0530 Subject: [PATCH 131/238] feat: add chinese translation for robot duplicate --- public/locales/zh.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index df45c45c9..b673b2376 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -288,5 +288,27 @@ "select_sheet": "选择Google Sheet", "selected_sheet": "已选择表格: {{name}} (ID: {{id}})" } + }, + "robot_duplication": { + "title": "复制机器人", + "descriptions": { + "purpose": "机器人复制功能用于从具有相同结构的页面提取数据。", + "example": "示例:如果您已经为{{url1}}创建了机器人,您可以复制它来抓取类似的页面(如{{url2}}),而无需从头开始训练机器人。", + "warning": "⚠️ 确保新页面与原始页面具有相同的结构。" + }, + "fields": { + "target_url": "机器人目标URL" + }, + "buttons": { + "duplicate": "复制机器人", + "cancel": "取消" + }, + "notifications": { + "robot_not_found": "找不到机器人详细信息。请重试。", + "url_required": "需要目标URL。", + "duplicate_success": "机器人复制成功。", + "duplicate_error": "更新目标URL失败。请重试。", + "unknown_error": "更新目标URL时发生错误。" + } } } \ No newline at end of file From 0d5cd711951892f92583654798d629b432b91d85 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:33:24 +0530 Subject: [PATCH 132/238] feat: add english translation for robot duplicate --- public/locales/en.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 322d21ca9..501c05c03 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -299,5 +299,27 @@ "notifications": { "sheet_selected": "Google Sheet selected successfully" } + }, + "robot_duplication": { + "title": "Duplicate Robot", + "descriptions": { + "purpose": "Robot duplication is useful to extract data from pages with the same structure.", + "example": "Example: If you've created a robot for {{url1}}, you can duplicate it to scrape similar pages like {{url2}} without training a robot from scratch.", + "warning": "⚠️ Ensure the new page has the same structure as the original page." + }, + "fields": { + "target_url": "Robot Target URL" + }, + "buttons": { + "duplicate": "Duplicate Robot", + "cancel": "Cancel" + }, + "notifications": { + "robot_not_found": "Could not find robot details. Please try again.", + "url_required": "Target URL is required.", + "duplicate_success": "Robot duplicated successfully.", + "duplicate_error": "Failed to update the Target URL. Please try again.", + "unknown_error": "An error occurred while updating the Target URL." + } } } \ No newline at end of file From f395f55a96a078f228cd8213231a63be9adfbd8a Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:33:41 +0530 Subject: [PATCH 133/238] feat: add japanese translation for robot duplicate --- public/locales/ja.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index a93cae72c..3afbf9979 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -288,5 +288,27 @@ "select_sheet": "Google Sheetを選択", "selected_sheet": "選択したシート: {{name}} (ID: {{id}})" } + }, + "robot_duplication": { + "title": "ロボットを複製", + "descriptions": { + "purpose": "ロボットの複製は、同じ構造のページからデータを抽出する際に便利です。", + "example": "例:{{url1}}用のロボットを作成した場合、ロボットを一から作り直すことなく、{{url2}}のような類似のページをスクレイピングするために複製できます。", + "warning": "⚠️ 新しいページが元のページと同じ構造であることを確認してください。" + }, + "fields": { + "target_url": "ロボットのターゲットURL" + }, + "buttons": { + "duplicate": "ロボットを複製", + "cancel": "キャンセル" + }, + "notifications": { + "robot_not_found": "ロボットの詳細が見つかりません。もう一度お試しください。", + "url_required": "ターゲットURLが必要です。", + "duplicate_success": "ロボットが正常に複製されました。", + "duplicate_error": "ターゲットURLの更新に失敗しました。もう一度お試しください。", + "unknown_error": "ターゲットURLの更新中にエラーが発生しました。" + } } } From cff34c2aff165aa1c079f7abfb16d54ed8ac21b0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:33:58 +0530 Subject: [PATCH 134/238] feat: add spanish translation for robot duplicate --- public/locales/es.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index e38ba1c7b..9ef9ede59 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -288,5 +288,27 @@ "select_sheet": "Seleccionar Google Sheet", "selected_sheet": "Hoja seleccionada: {{name}} (ID: {{id}})" } + }, + "robot_duplication": { + "title": "Duplicar Robot", + "descriptions": { + "purpose": "La duplicación de robots es útil para extraer datos de páginas con la misma estructura.", + "example": "Ejemplo: Si has creado un robot para {{url1}}, puedes duplicarlo para extraer páginas similares como {{url2}} sin tener que entrenar un robot desde cero.", + "warning": "⚠️ Asegúrate de que la nueva página tenga la misma estructura que la página original." + }, + "fields": { + "target_url": "URL Destino del Robot" + }, + "buttons": { + "duplicate": "Duplicar Robot", + "cancel": "Cancelar" + }, + "notifications": { + "robot_not_found": "No se pudieron encontrar los detalles del robot. Por favor, inténtalo de nuevo.", + "url_required": "Se requiere la URL de destino.", + "duplicate_success": "Robot duplicado con éxito.", + "duplicate_error": "Error al actualizar la URL de destino. Por favor, inténtalo de nuevo.", + "unknown_error": "Ocurrió un error al actualizar la URL de destino." + } } } \ No newline at end of file From 553201d0dd3b8542c42daaafe8b5b0be44e4bd5f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:34:16 +0530 Subject: [PATCH 135/238] feat: add german translation for robot duplicate --- public/locales/de.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 0e8b5832f..302c16fe4 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -287,5 +287,27 @@ "select_sheet": "Google Sheet auswählen", "selected_sheet": "Ausgewähltes Sheet: {{name}} (ID: {{id}})" } + }, + "robot_duplication": { + "title": "Roboter duplizieren", + "descriptions": { + "purpose": "Die Roboter-Duplizierung ist nützlich, um Daten von Seiten mit der gleichen Struktur zu extrahieren.", + "example": "Beispiel: Wenn Sie einen Roboter für {{url1}} erstellt haben, können Sie ihn duplizieren, um ähnliche Seiten wie {{url2}} zu durchsuchen, ohne einen Roboter von Grund auf neu zu trainieren.", + "warning": "⚠️ Stellen Sie sicher, dass die neue Seite die gleiche Struktur wie die Originalseite hat." + }, + "fields": { + "target_url": "Roboter Ziel-URL" + }, + "buttons": { + "duplicate": "Roboter duplizieren", + "cancel": "Abbrechen" + }, + "notifications": { + "robot_not_found": "Roboterdetails konnten nicht gefunden werden. Bitte versuchen Sie es erneut.", + "url_required": "Ziel-URL ist erforderlich.", + "duplicate_success": "Roboter erfolgreich dupliziert.", + "duplicate_error": "Fehler beim Aktualisieren der Ziel-URL. Bitte versuchen Sie es erneut.", + "unknown_error": "Beim Aktualisieren der Ziel-URL ist ein Fehler aufgetreten." + } } } From 9b9a44df40be04a3f9f31d598bffd263cfa0d356 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:35:12 +0530 Subject: [PATCH 136/238] feat: add translation for robot duplicate --- src/components/molecules/RobotDuplicate.tsx | 50 +++++++++++---------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/components/molecules/RobotDuplicate.tsx b/src/components/molecules/RobotDuplicate.tsx index 38b7b4224..530aedc6f 100644 --- a/src/components/molecules/RobotDuplicate.tsx +++ b/src/components/molecules/RobotDuplicate.tsx @@ -6,6 +6,7 @@ import { useGlobalInfoStore } from '../../context/globalInfo'; import { duplicateRecording, getStoredRecording } from '../../api/storage'; import { WhereWhatPair } from 'maxun-core'; import { getUserById } from "../../api/auth"; +import { useTranslation } from 'react-i18next'; interface RobotMeta { name: string; @@ -54,6 +55,7 @@ interface RobotSettingsProps { } export const RobotDuplicationModal = ({ isOpen, handleStart, handleClose, initialSettings }: RobotSettingsProps) => { + const { t } = useTranslation(); const [robot, setRobot] = useState(null); const [targetUrl, setTargetUrl] = useState(''); const { recordingId, notify } = useGlobalInfoStore(); @@ -65,7 +67,6 @@ export const RobotDuplicationModal = ({ isOpen, handleStart, handleClose, initia }, [isOpen]); useEffect(() => { - // Update the targetUrl when the robot data is loaded if (robot) { const lastPair = robot?.recording.workflow[robot?.recording.workflow.length - 1]; const url = lastPair?.what.find(action => action.action === "goto")?.args?.[0]; @@ -78,22 +79,17 @@ export const RobotDuplicationModal = ({ isOpen, handleStart, handleClose, initia const robot = await getStoredRecording(recordingId); setRobot(robot); } else { - notify('error', 'Could not find robot details. Please try again.'); + notify('error', t('robot_duplication.notifications.robot_not_found')); } } - // const lastPair = robot?.recording.workflow[robot?.recording.workflow.length - 1]; - - // // Find the `goto` action in `what` and retrieve its arguments - // const targetUrl = lastPair?.what.find(action => action.action === "goto")?.args?.[0]; - const handleTargetUrlChange = (e: React.ChangeEvent) => { setTargetUrl(e.target.value); }; const handleSave = async () => { if (!robot || !targetUrl) { - notify('error', 'Target URL is required.'); + notify('error', t('robot_duplication.notifications.url_required')); return; } @@ -103,18 +99,18 @@ export const RobotDuplicationModal = ({ isOpen, handleStart, handleClose, initia const success = await duplicateRecording(robot.recording_meta.id, targetUrl); if (success) { - notify('success', 'Robot duplicated successfully.'); - handleStart(robot); // Inform parent about the updated robot + notify('success', t('robot_duplication.notifications.duplicate_success')); + handleStart(robot); handleClose(); setTimeout(() => { window.location.reload(); }, 1000); } else { - notify('error', 'Failed to update the Target URL. Please try again.'); + notify('error', t('robot_duplication.notifications.duplicate_error')); } } catch (error) { - notify('error', 'An error occurred while updating the Target URL.'); + notify('error', t('robot_duplication.notifications.unknown_error')); console.error('Error updating Target URL:', error); } }; @@ -126,34 +122,40 @@ export const RobotDuplicationModal = ({ isOpen, handleStart, handleClose, initia modalStyle={modalStyle} > <> - Duplicate Robot + + {t('robot_duplication.title')} + { robot && ( <> - Robot duplication is useful to extract data from pages with the same structure. -
- Example: If you've created a robot for producthunt.com/topics/api, you can duplicate it to scrape similar pages - like producthunt.com/topics/database without training a robot from scratch. - -
+ {t('robot_duplication.descriptions.purpose')} + +
+ producthunt.com/topics/api
', + url2: 'producthunt.com/topics/database' + }) + }}/> +
- ⚠️ Ensure the new page has the same structure as the original page. + {t('robot_duplication.descriptions.warning')} From 277f8a0d2b06c3993aec890843fe65babed38d21 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:38:32 +0530 Subject: [PATCH 137/238] feat: add german translation for runs table --- public/locales/de.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/de.json b/public/locales/de.json index 302c16fe4..bbf130a7f 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -55,7 +55,11 @@ "finishedAt": "Beendet am", "delete": "Löschen", "settings": "Einstellungen", - "search": "Ausführungen suchen..." + "search": "Ausführungen suchen...", + "notifications": { + "no_runs": "Keine Ausführungen gefunden. Bitte versuchen Sie es erneut.", + "delete_success": "Ausführung erfolgreich gelöscht" + } }, "proxy": { "title": "Proxy-Konfiguration", From 4de1f6ff14e2526b2c2de772aae05939f685455b Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:38:46 +0530 Subject: [PATCH 138/238] feat: add japanese translation for runs table --- public/locales/ja.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/ja.json b/public/locales/ja.json index 3afbf9979..88e97a7a1 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -56,7 +56,11 @@ "finishedAt": "終了日時", "delete": "削除", "settings": "設定", - "search": "実行を検索..." + "search": "実行を検索...", + "notifications": { + "no_runs": "実行が見つかりません。もう一度お試しください。", + "delete_success": "実行が正常に削除されました" + } }, "proxy": { "title": "プロキシ設定", From 4d5226e236a91cb1d481e67f6f3ffb2e0192e503 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:39:03 +0530 Subject: [PATCH 139/238] feat: add english translation for runs table --- public/locales/en.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/en.json b/public/locales/en.json index 501c05c03..567fdbad2 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -58,7 +58,11 @@ "finishedAt":"Finished At", "delete":"Delete", "settings":"Settings", - "search":"Search Runs..." + "search":"Search Runs...", + "notifications": { + "no_runs": "No runs found. Please try again.", + "delete_success": "Run deleted successfully" + } }, "proxy": { "title": "Proxy Configuration", From 55161e662b401414e94c738b9b442d7b2f5616ef Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:39:17 +0530 Subject: [PATCH 140/238] feat: add spanish translation for runs table --- public/locales/es.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/es.json b/public/locales/es.json index 9ef9ede59..b0653bd72 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -56,7 +56,11 @@ "finishedAt": "Finalizado el", "delete": "Eliminar", "settings": "Ajustes", - "search": "Buscar ejecuciones..." + "search": "Buscar ejecuciones...", + "notifications": { + "no_runs": "No se encontraron ejecuciones. Por favor, inténtelo de nuevo.", + "delete_success": "Ejecución eliminada con éxito" + } }, "proxy": { "title": "Configuración del Proxy", From 413d488cbb35b0f5deda9afa923838e5a04d90d3 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:39:32 +0530 Subject: [PATCH 141/238] feat: add chinese translation for runs table --- public/locales/zh.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index b673b2376..f1bc8b730 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -56,7 +56,11 @@ "finishedAt": "结束时间", "delete": "删除", "settings": "设置", - "search": "搜索运行记录..." + "search": "搜索运行记录...", + "notifications": { + "no_runs": "未找到运行记录。请重试。", + "delete_success": "运行记录删除成功" + } }, "proxy": { "title": "代理设置", From 85a32b5e39c137b701f6184b8d44be164fb6ccf3 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 13:39:52 +0530 Subject: [PATCH 142/238] feat: add translation for runs table --- src/components/molecules/RunsTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/molecules/RunsTable.tsx b/src/components/molecules/RunsTable.tsx index 41dd047a3..cc64672db 100644 --- a/src/components/molecules/RunsTable.tsx +++ b/src/components/molecules/RunsTable.tsx @@ -105,7 +105,7 @@ export const RunsTable: React.FC = ({ })); setRows(parsedRows); } else { - notify('error', 'No runs found. Please try again.'); + notify('error', t('runstable.notifications.no_runs')); } }; @@ -118,7 +118,7 @@ export const RunsTable: React.FC = ({ const handleDelete = () => { setRows([]); - notify('success', 'Run deleted successfully'); + notify('success', t('runstable.notifications.delete_success')); fetchRuns(); }; From 117d9d16e44c427c7ba022e2208134d593aaa998 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:16:52 +0530 Subject: [PATCH 143/238] feat: add chinese translation for recordings table --- public/locales/zh.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index f1bc8b730..cf24d3f7c 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -38,7 +38,11 @@ "edit": "编辑", "delete": "删除", "duplicate": "复制", - "search": "搜索机器人..." + "search": "搜索机器人...", + "notifications": { + "delete_warning": "无法删除机器人,因为它有关联的运行记录", + "delete_success": "机器人删除成功" + } }, "mainmenu": { "recordings": "机器人", From a9515ce42ae60b91015b558a701130bbcec362f4 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:17:17 +0530 Subject: [PATCH 144/238] feat: add german translation for recordings table --- public/locales/de.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/de.json b/public/locales/de.json index bbf130a7f..397acaaa6 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -37,7 +37,11 @@ }, "edit": "Bearbeiten", "delete": "Löschen", - "duplicate": "Duplizieren" + "duplicate": "Duplizieren", + "notifications": { + "delete_warning": "Roboter kann nicht gelöscht werden, da zugehörige Ausführungen vorhanden sind", + "delete_success": "Roboter erfolgreich gelöscht" + } }, "mainmenu": { "recordings": "Roboter", From 3e1a15a1927b7be919e85b300f90529ede18e948 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:17:31 +0530 Subject: [PATCH 145/238] feat: add spanish translation for recordings table --- public/locales/es.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/es.json b/public/locales/es.json index b0653bd72..3ea532be6 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -38,7 +38,11 @@ "edit": "Editar", "delete": "Eliminar", "duplicate": "Duplicar", - "search": "Buscar robots..." + "search": "Buscar robots...", + "notifications": { + "delete_warning": "No se puede eliminar el robot ya que tiene ejecuciones asociadas", + "delete_success": "Robot eliminado exitosamente" + } }, "mainmenu": { "recordings": "Robots", From fc7d869e8dcaf64a10eaa11c49f4fa052266c7ac Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:17:47 +0530 Subject: [PATCH 146/238] feat: add japanese translation for recordings table --- public/locales/ja.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/locales/ja.json b/public/locales/ja.json index 88e97a7a1..2f2ebeb61 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -38,7 +38,11 @@ "edit": "編集", "delete": "削除", "duplicate": "複製", - "search": "ロボットを検索..." + "search": "ロボットを検索...", + "notifications": { + "delete_warning": "関連する実行があるため、ロボットを削除できません", + "delete_success": "ロボットが正常に削除されました" + } }, "mainmenu": { "recordings": "ロボット", From 5f9d21b1406922d4bc5c511ec4749d909df4741e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:18:01 +0530 Subject: [PATCH 147/238] feat: add english translation for recordings table --- public/locales/en.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index 567fdbad2..3e350350b 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -38,8 +38,11 @@ "edit":"Edit", "delete":"Delete", "duplicate":"Duplicate", - "search":"Search Robots..." - + "search":"Search Robots...", + "notifications": { + "delete_warning": "Cannot delete robot as it has associated runs", + "delete_success": "Robot deleted successfully" + } }, "mainmenu":{ "recordings": "Robots", From 4a18bfc5fd88bcc75231b2b1867be7534b0026d1 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:18:16 +0530 Subject: [PATCH 148/238] feat: add translation for recordings table --- src/components/molecules/RecordingsTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/molecules/RecordingsTable.tsx b/src/components/molecules/RecordingsTable.tsx index 92bf572a4..01bc524b9 100644 --- a/src/components/molecules/RecordingsTable.tsx +++ b/src/components/molecules/RecordingsTable.tsx @@ -261,14 +261,14 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl checkRunsForRecording(row.id).then((result: boolean) => { if (result) { - notify('warning', 'Cannot delete robot as it has associated runs'); + notify('warning', t('recordingtable.notifications.delete_warning')); } }) deleteRecordingFromStorage(row.id).then((result: boolean) => { if (result) { setRows([]); - notify('success', 'Robot deleted successfully'); + notify('success', t('recordingtable.notifications.delete_success')); fetchRecordings(); } }) From 6b8d966574234915957518795e447cec7154872e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:31:54 +0530 Subject: [PATCH 149/238] feat: add english translation for robot settings --- public/locales/en.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 3e350350b..cd3c7f5f8 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -328,5 +328,16 @@ "duplicate_error": "Failed to update the Target URL. Please try again.", "unknown_error": "An error occurred while updating the Target URL." } + }, + "robot_settings": { + "title": "Robot Settings", + "target_url": "Robot Target URL", + "robot_id": "Robot ID", + "robot_limit": "Robot Limit", + "created_by_user": "Created By User", + "created_at": "Robot Created At", + "errors": { + "robot_not_found": "Could not find robot details. Please try again." + } } } \ No newline at end of file From 9850ff8ee9043390e68ca56310c9e7038bb6ffee Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:33:03 +0530 Subject: [PATCH 150/238] feat: add japanesetranslation for robot settings --- public/locales/ja.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 2f2ebeb61..093d56436 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -318,5 +318,16 @@ "duplicate_error": "ターゲットURLの更新に失敗しました。もう一度お試しください。", "unknown_error": "ターゲットURLの更新中にエラーが発生しました。" } + }, + "robot_settings": { + "title": "ロボット設定", + "target_url": "ロボットのターゲットURL", + "robot_id": "ロボットID", + "robot_limit": "ロボットの制限", + "created_by_user": "作成したユーザー", + "created_at": "作成日時", + "errors": { + "robot_not_found": "ロボットの詳細が見つかりませんでした。もう一度試してください。" + } } } From 5f7195841afda9431056f5414e44e14efa94fa26 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:33:27 +0530 Subject: [PATCH 151/238] feat: add spanish translation for robot settings --- public/locales/es.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 3ea532be6..e6609b5d2 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -318,5 +318,16 @@ "duplicate_error": "Error al actualizar la URL de destino. Por favor, inténtalo de nuevo.", "unknown_error": "Ocurrió un error al actualizar la URL de destino." } + }, + "robot_settings": { + "title": "Configuración del Robot", + "target_url": "URL de Destino del Robot", + "robot_id": "ID del Robot", + "robot_limit": "Límite del Robot", + "created_by_user": "Creado por Usuario", + "created_at": "Fecha de Creación del Robot", + "errors": { + "robot_not_found": "No se pudieron encontrar los detalles del robot. Inténtelo de nuevo." + } } } \ No newline at end of file From 262590b360b1cced526eb28818d502257f76204e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:33:43 +0530 Subject: [PATCH 152/238] feat: add german translation for robot settings --- public/locales/de.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 397acaaa6..d5cfae4fe 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -317,5 +317,16 @@ "duplicate_error": "Fehler beim Aktualisieren der Ziel-URL. Bitte versuchen Sie es erneut.", "unknown_error": "Beim Aktualisieren der Ziel-URL ist ein Fehler aufgetreten." } + }, + "robot_settings": { + "title": "Roboter-Einstellungen", + "target_url": "Roboter-Ziel-URL", + "robot_id": "Roboter-ID", + "robot_limit": "Roboter-Limit", + "created_by_user": "Erstellt von Benutzer", + "created_at": "Erstellungsdatum des Roboters", + "errors": { + "robot_not_found": "Roboterdetails konnten nicht gefunden werden. Bitte versuchen Sie es erneut." + } } } From e922a11331aba928e131d148a12d71b3e6eb9c94 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:34:11 +0530 Subject: [PATCH 153/238] feat: add chinese translation for robot settings --- public/locales/zh.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index cf24d3f7c..9b5e7fb84 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -318,5 +318,16 @@ "duplicate_error": "更新目标URL失败。请重试。", "unknown_error": "更新目标URL时发生错误。" } + }, + "robot_settings": { + "title": "机器人设置", + "target_url": "机器人目标URL", + "robot_id": "机器人ID", + "robot_limit": "机器人限制", + "created_by_user": "由用户创建", + "created_at": "机器人创建时间", + "errors": { + "robot_not_found": "无法找到机器人详细信息。请重试。" + } } } \ No newline at end of file From 4e375e638071f00581fb26e2ecf76d49e6d4f43c Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:34:31 +0530 Subject: [PATCH 154/238] feat: add translation for robot settings --- src/components/molecules/RobotSettings.tsx | 25 ++++++++++++---------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/components/molecules/RobotSettings.tsx b/src/components/molecules/RobotSettings.tsx index 53d21d7bb..d952f43de 100644 --- a/src/components/molecules/RobotSettings.tsx +++ b/src/components/molecules/RobotSettings.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { GenericModal } from "../atoms/GenericModal"; import { TextField, Typography, Box } from "@mui/material"; import { modalStyle } from "./AddWhereCondModal"; @@ -50,10 +51,10 @@ interface RobotSettingsProps { handleStart: (settings: RobotSettings) => void; handleClose: () => void; initialSettings?: RobotSettings | null; - } export const RobotSettingsModal = ({ isOpen, handleStart, handleClose, initialSettings }: RobotSettingsProps) => { + const { t } = useTranslation(); const [robot, setRobot] = useState(null); const [userEmail, setUserEmail] = useState(null); const { recordingId, notify } = useGlobalInfoStore(); @@ -69,7 +70,7 @@ export const RobotSettingsModal = ({ isOpen, handleStart, handleClose, initialSe const robot = await getStoredRecording(recordingId); setRobot(robot); } else { - notify('error', 'Could not find robot details. Please try again.'); + notify('error', t('robot_settings.errors.robot_not_found')); } } @@ -97,13 +98,15 @@ export const RobotSettingsModal = ({ isOpen, handleStart, handleClose, initialSe modalStyle={modalStyle} > <> - Robot Settings + + {t('robot_settings.title')} + { robot && ( <> {robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== undefined && ( )} ); -}; +}; \ No newline at end of file From 16496fb66843e353652f97733ea5cca3c33f51c6 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:39:02 +0530 Subject: [PATCH 155/238] feat: add chinese translation for robot edit --- public/locales/zh.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 9b5e7fb84..f3954efc8 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -329,5 +329,17 @@ "errors": { "robot_not_found": "无法找到机器人详细信息。请重试。" } + }, + "robot_edit": { + "title": "编辑机器人", + "change_name": "更改机器人名称", + "robot_limit": "机器人限制", + "save": "保存更改", + "cancel": "取消", + "notifications": { + "update_success": "机器人更新成功。", + "update_failed": "无法更新机器人。请重试。", + "update_error": "更新机器人时发生错误。" + } } } \ No newline at end of file From d84ff7216eb3b10a0fc47fe37897d4ea0d7ad248 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:39:20 +0530 Subject: [PATCH 156/238] feat: add english translation for robot edit --- public/locales/en.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index cd3c7f5f8..f14840a77 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -339,5 +339,17 @@ "errors": { "robot_not_found": "Could not find robot details. Please try again." } + }, + "robot_edit": { + "title": "Edit Robot", + "change_name": "Change Robot Name", + "robot_limit": "Robot Limit", + "save": "Save Changes", + "cancel": "Cancel", + "notifications": { + "update_success": "Robot updated successfully.", + "update_failed": "Failed to update the robot. Please try again.", + "update_error": "An error occurred while updating the robot." + } } } \ No newline at end of file From 6bed79d14e8334729754d579386ec37e77948d2b Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:39:36 +0530 Subject: [PATCH 157/238] feat: add japanese translation for robot edit --- public/locales/ja.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 093d56436..fdc0c9290 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -329,5 +329,17 @@ "errors": { "robot_not_found": "ロボットの詳細が見つかりませんでした。もう一度試してください。" } + }, + "robot_edit": { + "title": "ロボットを編集", + "change_name": "ロボット名の変更", + "robot_limit": "ロボットの制限", + "save": "変更を保存", + "cancel": "キャンセル", + "notifications": { + "update_success": "ロボットが正常に更新されました。", + "update_failed": "ロボットの更新に失敗しました。もう一度試してください。", + "update_error": "ロボットの更新中にエラーが発生しました。" + } } } From e0f1a095f350584eb1eecf0cbd0bab0514a2af73 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:39:50 +0530 Subject: [PATCH 158/238] feat: add spanish translation for robot edit --- public/locales/es.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index e6609b5d2..58ccdef71 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -329,5 +329,17 @@ "errors": { "robot_not_found": "No se pudieron encontrar los detalles del robot. Inténtelo de nuevo." } + }, + "robot_edit": { + "title": "Editar Robot", + "change_name": "Cambiar Nombre del Robot", + "robot_limit": "Límite del Robot", + "save": "Guardar Cambios", + "cancel": "Cancelar", + "notifications": { + "update_success": "Robot actualizado exitosamente.", + "update_failed": "Error al actualizar el robot. Intente de nuevo.", + "update_error": "Ocurrió un error al actualizar el robot." + } } } \ No newline at end of file From 5be29d55cfca55189cf1ad4ee93bcf7414146b70 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:40:01 +0530 Subject: [PATCH 159/238] feat: add german translation for robot edit --- public/locales/de.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index d5cfae4fe..49332b761 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -328,5 +328,17 @@ "errors": { "robot_not_found": "Roboterdetails konnten nicht gefunden werden. Bitte versuchen Sie es erneut." } + }, + "robot_edit": { + "title": "Roboter bearbeiten", + "change_name": "Roboternamen ändern", + "robot_limit": "Roboter-Limit", + "save": "Änderungen speichern", + "cancel": "Abbrechen", + "notifications": { + "update_success": "Roboter erfolgreich aktualisiert.", + "update_failed": "Aktualisierung des Roboters fehlgeschlagen. Bitte erneut versuchen.", + "update_error": "Beim Aktualisieren des Roboters ist ein Fehler aufgetreten." + } } } From f4a99fbfc2a087e1bd83780d390a33112e8cc5ff Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 15:42:35 +0530 Subject: [PATCH 160/238] feat: add translation for robot edit --- src/components/molecules/RobotEdit.tsx | 31 +++++++++++++++++--------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/components/molecules/RobotEdit.tsx b/src/components/molecules/RobotEdit.tsx index 9441ecefa..73397da41 100644 --- a/src/components/molecules/RobotEdit.tsx +++ b/src/components/molecules/RobotEdit.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { GenericModal } from "../atoms/GenericModal"; import { TextField, Typography, Box, Button } from "@mui/material"; import { modalStyle } from "./AddWhereCondModal"; @@ -54,10 +55,10 @@ interface RobotSettingsProps { handleStart: (settings: RobotSettings) => void; handleClose: () => void; initialSettings?: RobotSettings | null; - } export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettings }: RobotSettingsProps) => { + const { t } = useTranslation(); const [robot, setRobot] = useState(null); const { recordingId, notify } = useGlobalInfoStore(); @@ -72,7 +73,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const robot = await getStoredRecording(recordingId); setRobot(robot); } else { - notify('error', 'Could not find robot details. Please try again.'); + notify('error', t('robot_edit.notifications.update_failed')); } } @@ -102,6 +103,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return { ...prev, recording: { ...prev.recording, workflow: updatedWorkflow } }; }); }; + const handleSave = async () => { if (!robot) return; @@ -114,7 +116,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const success = await updateRecording(robot.recording_meta.id, payload); if (success) { - notify('success', 'Robot updated successfully.'); + notify('success', t('robot_edit.notifications.update_success')); handleStart(robot); // Inform parent about the updated robot handleClose(); @@ -122,10 +124,10 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin window.location.reload(); }, 1000); } else { - notify('error', 'Failed to update the robot. Please try again.'); + notify('error', t('robot_edit.notifications.update_failed')); } } catch (error) { - notify('error', 'An error occurred while updating the robot.'); + notify('error', t('robot_edit.notifications.update_error')); console.error('Error updating robot:', error); } }; @@ -137,13 +139,15 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin modalStyle={modalStyle} > <> - Edit Robot + + {t('robot_edit.title')} + { robot && ( <> {robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== undefined && ( { @@ -168,10 +172,15 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin - From 5b4a4e710e86f3039b5547acca6d5d8d0dd57083 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:02:25 +0530 Subject: [PATCH 161/238] feat: add german translation for schedule settings --- public/locales/de.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 49332b761..184a918bf 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -340,5 +340,30 @@ "update_failed": "Aktualisierung des Roboters fehlgeschlagen. Bitte erneut versuchen.", "update_error": "Beim Aktualisieren des Roboters ist ein Fehler aufgetreten." } + }, + "schedule_settings": { + "title": "Zeitplan-Einstellungen", + "run_every": "Ausführen alle", + "start_from": "Beginnen ab", + "on_day": "An Tag", + "at_around": "Um", + "timezone": "Zeitzone", + "buttons": { + "delete_schedule": "Zeitplan löschen", + "save_schedule": "Zeitplan speichern", + "cancel": "Abbrechen" + }, + "labels": { + "in_between": "Zwischen", + "run_once_every": "Ausführen alle", + "start_from_label": "Beginnen ab", + "on_day_of_month": "Tag des Monats", + "on_day": { + "st": ".", + "nd": ".", + "rd": ".", + "th": "." + } + } } } From b15fe34bbc9c0abe47fd96a51a456e6a51e41d0d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:02:46 +0530 Subject: [PATCH 162/238] feat: add japanese translation for schedule settings --- public/locales/ja.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index fdc0c9290..9d93ce477 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -341,5 +341,30 @@ "update_failed": "ロボットの更新に失敗しました。もう一度試してください。", "update_error": "ロボットの更新中にエラーが発生しました。" } + }, + "schedule_settings": { + "title": "スケジュール設定", + "run_every": "実行間隔", + "start_from": "開始日", + "on_day": "日付", + "at_around": "時刻", + "timezone": "タイムゾーン", + "buttons": { + "delete_schedule": "スケジュールを削除", + "save_schedule": "スケジュールを保存", + "cancel": "キャンセル" + }, + "labels": { + "in_between": "間隔", + "run_once_every": "実行間隔", + "start_from_label": "開始日", + "on_day_of_month": "月の日付", + "on_day": { + "st": "日", + "nd": "日", + "rd": "日", + "th": "日" + } + } } } From 8a68712f34efd1567e270d428fbbcd0785386a15 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:02:59 +0530 Subject: [PATCH 163/238] feat: add english translation for schedule settings --- public/locales/en.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index f14840a77..580a65209 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -351,5 +351,30 @@ "update_failed": "Failed to update the robot. Please try again.", "update_error": "An error occurred while updating the robot." } + }, + "schedule_settings": { + "title": "Schedule Settings", + "run_every": "Run every", + "start_from": "Start From", + "on_day": "On day", + "at_around": "At around", + "timezone": "Timezone", + "buttons": { + "delete_schedule": "Delete Schedule", + "save_schedule": "Save Schedule", + "cancel": "Cancel" + }, + "labels": { + "in_between": "In Between", + "run_once_every": "Run once every", + "start_from_label": "Start From", + "on_day_of_month": "On Day of the Month", + "on_day": { + "st": "st", + "nd": "nd", + "rd": "rd", + "th": "th" + } + } } } \ No newline at end of file From 9b28e00ae517d0ee0d919f5dc73440e6a6a0c5a0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:03:14 +0530 Subject: [PATCH 164/238] feat: add spanish translation for schedule settings --- public/locales/es.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 58ccdef71..7e429d3b4 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -341,5 +341,30 @@ "update_failed": "Error al actualizar el robot. Intente de nuevo.", "update_error": "Ocurrió un error al actualizar el robot." } + }, + "schedule_settings": { + "title": "Configuración de Programación", + "run_every": "Ejecutar cada", + "start_from": "Iniciar desde", + "on_day": "En día", + "at_around": "Alrededor de", + "timezone": "Zona horaria", + "buttons": { + "delete_schedule": "Eliminar Programación", + "save_schedule": "Guardar Programación", + "cancel": "Cancelar" + }, + "labels": { + "in_between": "Entre", + "run_once_every": "Ejecutar cada", + "start_from_label": "Iniciar desde", + "on_day_of_month": "Día del mes", + "on_day": { + "st": "º", + "nd": "º", + "rd": "º", + "th": "º" + } + } } } \ No newline at end of file From 86ef4edf1a8139841e4108db1bdf2d0755f38bd2 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:03:31 +0530 Subject: [PATCH 165/238] feat: add chinese translation for schedule settings --- public/locales/zh.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index f3954efc8..436e74dbe 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -341,5 +341,30 @@ "update_failed": "无法更新机器人。请重试。", "update_error": "更新机器人时发生错误。" } + }, + "schedule_settings": { + "title": "计划设置", + "run_every": "每次运行", + "start_from": "开始于", + "on_day": "在日", + "at_around": "大约在", + "timezone": "时区", + "buttons": { + "delete_schedule": "删除计划", + "save_schedule": "保存计划", + "cancel": "取消" + }, + "labels": { + "in_between": "之间", + "run_once_every": "每次运行", + "start_from_label": "开始于", + "on_day_of_month": "月份日期", + "on_day": { + "st": "日", + "nd": "日", + "rd": "日", + "th": "日" + } + } } } \ No newline at end of file From 90a6c54a16311ebe1a78bf3b46a159975b1e02df Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:03:50 +0530 Subject: [PATCH 166/238] feat: add translation for schedule settings --- src/components/molecules/ScheduleSettings.tsx | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/components/molecules/ScheduleSettings.tsx b/src/components/molecules/ScheduleSettings.tsx index 00e842ea5..3af0072fc 100644 --- a/src/components/molecules/ScheduleSettings.tsx +++ b/src/components/molecules/ScheduleSettings.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { GenericModal } from "../atoms/GenericModal"; import { MenuItem, TextField, Typography, Box } from "@mui/material"; import { Dropdown } from "../atoms/DropdownMui"; @@ -25,6 +26,7 @@ export interface ScheduleSettings { } export const ScheduleSettingsModal = ({ isOpen, handleStart, handleClose, initialSettings }: ScheduleSettingsProps) => { + const { t } = useTranslation(); const [schedule, setSchedule] = useState(null); const [settings, setSettings] = useState({ runEvery: 1, @@ -116,6 +118,25 @@ export const ScheduleSettingsModal = ({ isOpen, handleStart, handleClose, initia } }, [isOpen]); + const getDayOrdinal = (day: string | undefined) => { + if (!day) return ''; + const lastDigit = day.slice(-1); + const lastTwoDigits = day.slice(-2); + + // Special cases for 11, 12, 13 + if (['11', '12', '13'].includes(lastTwoDigits)) { + return t('schedule_settings.labels.on_day.th'); + } + + // Other cases + switch (lastDigit) { + case '1': return t('schedule_settings.labels.on_day.st'); + case '2': return t('schedule_settings.labels.on_day.nd'); + case '3': return t('schedule_settings.labels.on_day.rd'); + default: return t('schedule_settings.labels.on_day.th'); + } + }; + return ( *': { marginBottom: '20px' }, }}> - Schedule Settings + {t('schedule_settings.title')} <> {schedule !== null ? ( <> - Run every: {schedule.runEvery} {schedule.runEveryUnit.toLowerCase()} - {['MONTHS', 'WEEKS'].includes(settings.runEveryUnit) ? "Start From" : "On"} {schedule.startFrom.charAt(0).toUpperCase() + schedule.startFrom.slice(1).toLowerCase()} + {t('schedule_settings.run_every')}: {schedule.runEvery} {schedule.runEveryUnit.toLowerCase()} + {['MONTHS', 'WEEKS'].includes(settings.runEveryUnit) ? t('schedule_settings.start_from') : t('schedule_settings.start_from')}: {schedule.startFrom.charAt(0).toUpperCase() + schedule.startFrom.slice(1).toLowerCase()} {schedule.runEveryUnit === 'MONTHS' && ( - On day: {schedule.dayOfMonth}{['1', '21', '31'].includes(schedule.dayOfMonth || '') ? 'st' : ['2', '22'].includes(schedule.dayOfMonth || '') ? 'nd' : ['3', '23'].includes(schedule.dayOfMonth || '') ? 'rd' : 'th'} of the month + {t('schedule_settings.on_day')}: {schedule.dayOfMonth}{getDayOrdinal(schedule.dayOfMonth)} of the month )} - At around: {schedule.atTimeStart}, {schedule.timezone} Timezone + {t('schedule_settings.at_around')}: {schedule.atTimeStart}, {schedule.timezone} {t('schedule_settings.timezone')} ) : ( <> - Run once every + {t('schedule_settings.labels.run_once_every')} - {['MONTHS', 'WEEKS'].includes(settings.runEveryUnit) ? "Start From" : "On"} + + {['MONTHS', 'WEEKS'].includes(settings.runEveryUnit) ? t('schedule_settings.labels.start_from_label') : t('schedule_settings.labels.start_from_label')} + - On Day of the Month + {t('schedule_settings.labels.on_day_of_month')} - In Between + {t('schedule_settings.labels.in_between')} ) : ( - At Around + {t('schedule_settings.at_around')} - Timezone + {t('schedule_settings.timezone')} @@ -271,4 +294,4 @@ const modalStyle = { height: 'fit-content', display: 'block', padding: '20px', -}; +}; \ No newline at end of file From 3020f96ddd438fd9686369d8f310b40f33283610 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:16:59 +0530 Subject: [PATCH 167/238] feat: add chinese translation for main page notifications --- public/locales/zh.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 436e74dbe..3032841fc 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -366,5 +366,23 @@ "th": "日" } } + }, + "main_page": { + "notifications": { + "interpretation_success": "机器人{{name}}解释成功", + "interpretation_failed": "机器人{{name}}解释失败", + "run_started": "正在运行机器人:{{name}}", + "run_start_failed": "机器人运行失败:{{name}}", + "schedule_success": "机器人{{name}}调度成功", + "schedule_failed": "机器人{{name}}调度失败", + "abort_success": "成功中止机器人{{name}}的解释", + "abort_failed": "中止机器人{{name}}的解释失败" + }, + "menu": { + "recordings": "机器人", + "runs": "运行", + "proxy": "代理", + "apikey": "API密钥" + } } } \ No newline at end of file From eb1c4ec3166a6e47a366dc44dabd35b408baf31c Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:17:17 +0530 Subject: [PATCH 168/238] feat: add spanish translation for main page notifications --- public/locales/es.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 7e429d3b4..5db7f0c73 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -366,5 +366,23 @@ "th": "º" } } + }, + "main_page": { + "notifications": { + "interpretation_success": "Interpretación del robot {{name}} completada con éxito", + "interpretation_failed": "Error al interpretar el robot {{name}}", + "run_started": "Ejecutando robot: {{name}}", + "run_start_failed": "Error al ejecutar el robot: {{name}}", + "schedule_success": "Robot {{name}} programado exitosamente", + "schedule_failed": "Error al programar el robot {{name}}", + "abort_success": "Interpretación del robot {{name}} abortada exitosamente", + "abort_failed": "Error al abortar la interpretación del robot {{name}}" + }, + "menu": { + "recordings": "Robots", + "runs": "Ejecuciones", + "proxy": "Proxy", + "apikey": "Clave API" + } } } \ No newline at end of file From bc4f5067083668ac188098107a38fe288f62fe64 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:17:31 +0530 Subject: [PATCH 169/238] feat: add japanese translation for main page notifications --- public/locales/ja.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 9d93ce477..7c15d9aff 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -366,5 +366,23 @@ "th": "日" } } + }, + "main_page": { + "notifications": { + "interpretation_success": "ロボット{{name}}の解釈に成功しました", + "interpretation_failed": "ロボット{{name}}の解釈に失敗しました", + "run_started": "ロボット{{name}}を実行中", + "run_start_failed": "ロボット{{name}}の実行に失敗しました", + "schedule_success": "ロボット{{name}}のスケジュールが正常に設定されました", + "schedule_failed": "ロボット{{name}}のスケジュール設定に失敗しました", + "abort_success": "ロボット{{name}}の解釈を中止しました", + "abort_failed": "ロボット{{name}}の解釈中止に失敗しました" + }, + "menu": { + "recordings": "ロボット", + "runs": "実行", + "proxy": "プロキシ", + "apikey": "APIキー" + } } } From 80cd1be84318c420b765ad6c5addebe74cad44dd Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:17:48 +0530 Subject: [PATCH 170/238] feat: add english translation for main page notifications --- public/locales/en.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 580a65209..5c40b87f2 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -376,5 +376,23 @@ "th": "th" } } + }, + "main_page": { + "notifications": { + "interpretation_success": "Interpretation of robot {{name}} succeeded", + "interpretation_failed": "Failed to interpret robot {{name}}", + "run_started": "Running robot: {{name}}", + "run_start_failed": "Failed to run robot: {{name}}", + "schedule_success": "Robot {{name}} scheduled successfully", + "schedule_failed": "Failed to schedule robot {{name}}", + "abort_success": "Interpretation of robot {{name}} aborted successfully", + "abort_failed": "Failed to abort the interpretation of robot {{name}}" + }, + "menu": { + "recordings": "Robots", + "runs": "Runs", + "proxy": "Proxy", + "apikey": "API Key" + } } } \ No newline at end of file From 5983594faa2715d6796ae0516d065d50e6eb7e53 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:18:05 +0530 Subject: [PATCH 171/238] feat: add german translation for main page notifications --- public/locales/de.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 184a918bf..2e99b4516 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -365,5 +365,23 @@ "th": "." } } + }, + "main_page": { + "notifications": { + "interpretation_success": "Interpretation des Roboters {{name}} erfolgreich", + "interpretation_failed": "Interpretation des Roboters {{name}} fehlgeschlagen", + "run_started": "Roboter wird ausgeführt: {{name}}", + "run_start_failed": "Fehler beim Ausführen des Roboters: {{name}}", + "schedule_success": "Roboter {{name}} erfolgreich geplant", + "schedule_failed": "Planen des Roboters {{name}} fehlgeschlagen", + "abort_success": "Interpretation des Roboters {{name}} erfolgreich abgebrochen", + "abort_failed": "Abbrechen der Interpretation des Roboters {{name}} fehlgeschlagen" + }, + "menu": { + "recordings": "Roboter", + "runs": "Ausführungen", + "proxy": "Proxy", + "apikey": "API-Schlüssel" + } } } From 3d4ec211e7d71edf3d16d99ff278200f790a6531 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:18:30 +0530 Subject: [PATCH 172/238] feat: add translation for main page notifications --- src/pages/MainPage.tsx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index 8af3d3c5e..4a82170e8 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { MainMenu } from "../components/organisms/MainMenu"; import { Stack } from "@mui/material"; import { Recordings } from "../components/organisms/Recordings"; @@ -30,7 +31,7 @@ export interface ScheduleRunResponse { } export const MainPage = ({ handleEditRecording }: MainPageProps) => { - + const { t } = useTranslation(); const [content, setContent] = React.useState('recordings'); const [sockets, setSockets] = React.useState([]); const [runningRecordingId, setRunningRecordingId] = React.useState(''); @@ -49,10 +50,10 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { aborted = true; notifyAboutAbort(runId).then(async (response) => { if (response) { - notify('success', `Interpretation of robot ${runningRecordingName} aborted successfully`); + notify('success', t('main_page.notifications.abort_success', { name: runningRecordingName })); await stopRecording(ids.browserId); } else { - notify('error', `Failed to abort the interpretation of ${runningRecordingName} robot`); + notify('error', t('main_page.notifications.abort_failed', { name: runningRecordingName })); } }) } @@ -67,9 +68,9 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { interpretStoredRecording(runId).then(async (interpretation: boolean) => { if (!aborted) { if (interpretation) { - notify('success', `Interpretation of robot ${runningRecordingName} succeeded`); + notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); } else { - notify('success', `Failed to interpret ${runningRecordingName} robot`); + notify('success', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); // destroy the created browser await stopRecording(browserId); } @@ -98,9 +99,9 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { socket.on('debugMessage', debugMessageHandler); setContent('runs'); if (browserId) { - notify('info', `Running robot: ${runningRecordingName}`); + notify('info', t('main_page.notifications.run_started', { name: runningRecordingName })); } else { - notify('error', `Failed to run robot: ${runningRecordingName}`); + notify('error', t('main_page.notifications.run_start_failed', { name: runningRecordingName })); } }) return (socket: Socket, browserId: string, runId: string) => { @@ -113,9 +114,9 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { scheduleStoredRecording(runningRecordingId, settings) .then(({ message, runId }: ScheduleRunResponse) => { if (message === 'success') { - notify('success', `Robot ${runningRecordingName} scheduled successfully`); + notify('success', t('main_page.notifications.schedule_success', { name: runningRecordingName })); } else { - notify('error', `Failed to schedule robot ${runningRecordingName}`); + notify('error', t('main_page.notifications.schedule_failed', { name: runningRecordingName })); } }); } @@ -151,4 +152,4 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => { {DisplayContent()} ); -}; +}; \ No newline at end of file From 329aff1ce98b5c377a9ce75d8dbdbe1b08e73cfb Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:19:04 +0530 Subject: [PATCH 173/238] feat: add translation for proxy form notifications --- src/components/organisms/ProxyForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/organisms/ProxyForm.tsx b/src/components/organisms/ProxyForm.tsx index 8fbf730af..46874349e 100644 --- a/src/components/organisms/ProxyForm.tsx +++ b/src/components/organisms/ProxyForm.tsx @@ -84,10 +84,10 @@ const ProxyForm: React.FC = () => { notify('success', t('proxy.notifications.config_success')); } else { notify('error', t('proxy.notifications.config_error')); - console.log(`Failed to submit proxy configuration. Try again. ${response}`) + console.log(`${t('proxy.notifications.config_error')} ${response}`) } } catch (error: any) { - notify('error', `${error} : Failed to submit proxy configuration`); + notify('error', `${error} : ${t('proxy.notifications.config_error')}`); } }; From e0c7acfb1908bd27b50fcaf6f8a0a2599bdb47c2 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:31:44 +0530 Subject: [PATCH 174/238] feat: add german translation for browser window notifications --- public/locales/de.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 2e99b4516..685fbd200 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -383,5 +383,27 @@ "proxy": "Proxy", "apikey": "API-Schlüssel" } + }, + "browser_window": { + "attribute_modal": { + "title": "Attribut auswählen", + "notifications": { + "list_select_success": "Liste erfolgreich ausgewählt. Wählen Sie die zu extrahierenden Textdaten.", + "pagination_select_success": "Paginierungselement erfolgreich ausgewählt." + } + }, + "attribute_options": { + "anchor": { + "text": "Text: {{text}}", + "url": "URL: {{url}}" + }, + "image": { + "alt_text": "Alt-Text: {{altText}}", + "image_url": "Bild-URL: {{imageUrl}}" + }, + "default": { + "text": "Text: {{text}}" + } + } } } From 6dafc7986c59d6970cfb613ea6abc00d270e7239 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:32:09 +0530 Subject: [PATCH 175/238] feat: add spanish translation for browser window notifications --- public/locales/es.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 5db7f0c73..69c61db68 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -384,5 +384,27 @@ "proxy": "Proxy", "apikey": "Clave API" } + }, + "browser_window": { + "attribute_modal": { + "title": "Seleccionar Atributo", + "notifications": { + "list_select_success": "Lista seleccionada correctamente. Seleccione los datos de texto para extracción.", + "pagination_select_success": "Elemento de paginación seleccionado correctamente." + } + }, + "attribute_options": { + "anchor": { + "text": "Texto: {{text}}", + "url": "URL: {{url}}" + }, + "image": { + "alt_text": "Texto Alt: {{altText}}", + "image_url": "URL de Imagen: {{imageUrl}}" + }, + "default": { + "text": "Texto: {{text}}" + } + } } } \ No newline at end of file From f92236fe0986b545e1c1008b63dd4eb68e0cf907 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:32:23 +0530 Subject: [PATCH 176/238] feat: add japanese translation for browser window notifications --- public/locales/ja.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index 7c15d9aff..596adebc1 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -384,5 +384,27 @@ "proxy": "プロキシ", "apikey": "APIキー" } + }, + "browser_window": { + "attribute_modal": { + "title": "属性を選択", + "notifications": { + "list_select_success": "リストが正常に選択されました。抽出するテキストデータを選択してください。", + "pagination_select_success": "ページネーション要素が正常に選択されました。" + } + }, + "attribute_options": { + "anchor": { + "text": "テキスト: {{text}}", + "url": "URL: {{url}}" + }, + "image": { + "alt_text": "代替テキスト: {{altText}}", + "image_url": "画像URL: {{imageUrl}}" + }, + "default": { + "text": "テキスト: {{text}}" + } + } } } From 7101eba88fff47642dc31fb18dfeb9ad9424f449 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:32:41 +0530 Subject: [PATCH 177/238] feat: add english translation for browser window notifications --- public/locales/en.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 5c40b87f2..7424872eb 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -394,5 +394,27 @@ "proxy": "Proxy", "apikey": "API Key" } + }, + "browser_window": { + "attribute_modal": { + "title": "属性を選択", + "notifications": { + "list_select_success": "リストが正常に選択されました。抽出するテキストデータを選択してください。", + "pagination_select_success": "ページネーション要素が正常に選択されました。" + } + }, + "attribute_options": { + "anchor": { + "text": "テキスト: {{text}}", + "url": "URL: {{url}}" + }, + "image": { + "alt_text": "代替テキスト: {{altText}}", + "image_url": "画像URL: {{imageUrl}}" + }, + "default": { + "text": "テキスト: {{text}}" + } + } } } \ No newline at end of file From 95c57591e00ea880a3a3ed4499c86743ac96be1f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:32:56 +0530 Subject: [PATCH 178/238] feat: add chinese translation for browser window notifications --- public/locales/zh.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 3032841fc..de9c85943 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -384,5 +384,27 @@ "proxy": "代理", "apikey": "API密钥" } + }, + "browser_window": { + "attribute_modal": { + "title": "选择属性", + "notifications": { + "list_select_success": "列表选择成功。选择要提取的文本数据。", + "pagination_select_success": "分页元素选择成功。" + } + }, + "attribute_options": { + "anchor": { + "text": "文本: {{text}}", + "url": "URL: {{url}}" + }, + "image": { + "alt_text": "替代文本: {{altText}}", + "image_url": "图像URL: {{imageUrl}}" + }, + "default": { + "text": "文本: {{text}}" + } + } } } \ No newline at end of file From 33ac9c3a2d69b39436aa058b93c73ec36fdcb55e Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:33:21 +0530 Subject: [PATCH 179/238] feat: add translation for browser window notifications --- src/components/organisms/BrowserWindow.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/organisms/BrowserWindow.tsx b/src/components/organisms/BrowserWindow.tsx index 697b4adb1..c7e9fc0f3 100644 --- a/src/components/organisms/BrowserWindow.tsx +++ b/src/components/organisms/BrowserWindow.tsx @@ -7,6 +7,7 @@ import { GenericModal } from '../atoms/GenericModal'; import { useActionContext } from '../../context/browserActions'; import { useBrowserSteps, TextStep } from '../../context/browserSteps'; import { useGlobalInfoStore } from '../../context/globalInfo'; +import { useTranslation } from 'react-i18next'; interface ElementInfo { @@ -52,6 +53,7 @@ const getAttributeOptions = (tagName: string, elementInfo: ElementInfo | null): }; export const BrowserWindow = () => { + const { t } = useTranslation(); const [canvasRef, setCanvasReference] = useState | undefined>(undefined); const [screenShot, setScreenShot] = useState(""); const [highlighterData, setHighlighterData] = useState<{ rect: DOMRect, selector: string, elementInfo: ElementInfo | null, childSelectors?: string[] } | null>(null); @@ -200,7 +202,7 @@ export const BrowserWindow = () => { // Only allow selection in pagination mode if type is not empty, 'scrollDown', or 'scrollUp' if (paginationType !== '' && paginationType !== 'scrollDown' && paginationType !== 'scrollUp' && paginationType !== 'none') { setPaginationSelector(highlighterData.selector); - notify(`info`, `Pagination element selected successfully.`); + notify(`info`, t('browser_window.attribute_modal.notifications.pagination_select_success')); addListStep(listSelector!, fields, currentListId || 0, { type: paginationType, selector: highlighterData.selector }); } return; @@ -208,7 +210,7 @@ export const BrowserWindow = () => { if (getList === true && !listSelector) { setListSelector(highlighterData.selector); - notify(`info`, `List selected succesfully. Select the text data for extraction.`) + notify(`info`, t('browser_window.attribute_modal.notifications.list_select_success')); setCurrentListId(Date.now()); setFields({}); } else if (getList === true && listSelector && currentListId) { From 70eed0c36cd578ddcef7034992bdefcb5d0ab8e8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:38:01 +0530 Subject: [PATCH 180/238] feat: add translation for integration settings notifications --- src/components/molecules/IntegrationSettings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/IntegrationSettings.tsx b/src/components/molecules/IntegrationSettings.tsx index 97973645f..15e5dad83 100644 --- a/src/components/molecules/IntegrationSettings.tsx +++ b/src/components/molecules/IntegrationSettings.tsx @@ -109,7 +109,7 @@ export const IntegrationSettingsModal = ({ }, { withCredentials: true } ); - notify(`success`, `Google Sheet selected successfully`) + notify(`success`, t('integration_settings.notifications.sheet_selected')); console.log("Google Sheet ID updated:", response.data); } catch (error: any) { console.error( From 3f0a58e584a465686eb5c7d505412716206b28af Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:42:32 +0530 Subject: [PATCH 181/238] feat: add translation for integration settings notifications --- src/components/molecules/IntegrationSettings.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/molecules/IntegrationSettings.tsx b/src/components/molecules/IntegrationSettings.tsx index 15e5dad83..c4b13e8cb 100644 --- a/src/components/molecules/IntegrationSettings.tsx +++ b/src/components/molecules/IntegrationSettings.tsx @@ -79,8 +79,9 @@ export const IntegrationSettingsModal = ({ ); notify( "error", - `Error fetching spreadsheet files: ${error.response?.data?.message || error.message - }` + t('integration_settings.errors.fetch_error', { + message: error.response?.data?.message || error.message + }) ); } }; From c8265a806038c8d4e3dbeda35f43f9dece682033 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:43:10 +0530 Subject: [PATCH 182/238] feat: add translation for navbar notifications --- src/components/molecules/NavBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 0658a7668..e5b26b96f 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -105,7 +105,7 @@ export const NavBar: React.FC = ({ const goToMainMenu = async () => { if (browserId) { await stopRecording(browserId); - notify("warning", "Current Recording was terminated"); + notify("warning", t('browser_recording.notifications.terminated')); setBrowserId(null); } navigate("/"); From 6e3724798796347c57316d9ad590308da34b795f Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:48:18 +0530 Subject: [PATCH 183/238] feat: add chinese translation for main menu --- public/locales/zh.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/zh.json b/public/locales/zh.json index de9c85943..0858cdf7a 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -50,7 +50,7 @@ "proxy": "代理", "apikey": "API密钥", "feedback": "加入 Maxun Cloud", - "apidocs": "API文档" + "apidocs": "网站转API" }, "runstable": { "runs": "所有运行记录", From 5d8f97179f7dba81acc420749eae567fc3a35ce7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:48:34 +0530 Subject: [PATCH 184/238] feat: add spanish translation for main menu --- public/locales/es.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/es.json b/public/locales/es.json index 69c61db68..1053a6df9 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -50,7 +50,7 @@ "proxy": "Proxy", "apikey": "Clave API", "feedback": "Unirse a Maxun Cloud", - "apidocs": "Documentación API" + "apidocs": "Sitio Web a API" }, "runstable": { "runs": "Todas las ejecuciones", From e3629d6007de1b4db94ee85cbdbab34e7fcb90f6 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:48:47 +0530 Subject: [PATCH 185/238] feat: add german translation for main menu --- public/locales/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/de.json b/public/locales/de.json index 685fbd200..7d09dc7e1 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -49,7 +49,7 @@ "proxy": "Proxy", "apikey": "API-Schlüssel", "feedback": "Maxun Cloud beitreten", - "apidocs": "API-Dokumentation" + "apidocs": "Website zu API" }, "runstable": { "runs": "Alle Ausführungen", From 6ecae3894035503b97118cbd9c70e87ea6d69fa8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:49:04 +0530 Subject: [PATCH 186/238] feat: add japanese translation for main menu --- public/locales/ja.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/ja.json b/public/locales/ja.json index 596adebc1..f99631eb8 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -50,7 +50,7 @@ "proxy": "プロキシ", "apikey": "APIキー", "feedback": "Maxunクラウドに参加する", - "apidocs": "APIドキュメント" + "apidocs": "WebサイトからAPI" }, "runstable": { "runs": "すべての実行", From e1bd600307c22131d77e728d1782cbef0dc4bcfd Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 16:49:19 +0530 Subject: [PATCH 187/238] feat: add english translation for main menu --- public/locales/en.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index 7424872eb..7176a56e6 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -50,8 +50,7 @@ "proxy": "Proxy", "apikey": "API Key", "feedback":"Join Maxun Cloud", - "apidocs":"API Docs" - + "apidocs":"Website To API" }, "runstable":{ "runs":"All Runs", From c95b1b8a244c1e44f325c1f67ecae1600eeea373 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:21:52 +0530 Subject: [PATCH 188/238] feat: add export to interface Data --- src/components/molecules/RunsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/RunsTable.tsx b/src/components/molecules/RunsTable.tsx index cc64672db..61e139ece 100644 --- a/src/components/molecules/RunsTable.tsx +++ b/src/components/molecules/RunsTable.tsx @@ -36,7 +36,7 @@ interface Column { format?: (value: string) => string; } -interface Data { +export interface Data { id: number; status: string; name: string; From 0fd870a1124409860f3a55fa16bac9adde70c620 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:29:20 +0530 Subject: [PATCH 189/238] feat: add chinese translation for collapsible row --- public/locales/zh.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 0858cdf7a..7fc99df06 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -406,5 +406,29 @@ "text": "文本: {{text}}" } } + }, + "runs_table": { + "run_type_chips": { + "manual_run": "手动运行", + "scheduled_run": "计划运行", + "api": "API", + "unknown_run_type": "未知运行类型" + }, + "run_status_chips": { + "success": "成功", + "running": "运行中", + "scheduled": "已计划", + "failed": "失败" + }, + "run_settings_modal": { + "title": "运行设置", + "labels": { + "run_id": "运行ID", + "run_by_user": "由用户运行", + "run_by_schedule": "按计划ID运行", + "run_by_api": "由API运行", + "run_type": "运行类型" + } + } } } \ No newline at end of file From f016c1a175e33d7bc75e939b9780d07f3bfbf6bf Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:29:37 +0530 Subject: [PATCH 190/238] feat: add german translation for collapsible row --- public/locales/de.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 7d09dc7e1..d33f413b9 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -405,5 +405,29 @@ "text": "Text: {{text}}" } } + }, + "runs_table": { + "run_type_chips": { + "manual_run": "Manuelle Ausführung", + "scheduled_run": "Geplante Ausführung", + "api": "API", + "unknown_run_type": "Unbekannter Ausführungstyp" + }, + "run_status_chips": { + "success": "Erfolg", + "running": "Läuft", + "scheduled": "Geplant", + "failed": "Fehlgeschlagen" + }, + "run_settings_modal": { + "title": "Ausführungseinstellungen", + "labels": { + "run_id": "Ausführungs-ID", + "run_by_user": "Ausgeführt von Benutzer", + "run_by_schedule": "Ausgeführt nach Zeitplan-ID", + "run_by_api": "Ausgeführt durch API", + "run_type": "Ausführungstyp" + } + } } } From 9765363ba83e0b71e1efd2cb25200b59df442726 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:29:52 +0530 Subject: [PATCH 191/238] feat: add spanish translation for collapsible row --- public/locales/es.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 1053a6df9..24dcad09a 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -406,5 +406,29 @@ "text": "Texto: {{text}}" } } + }, + "runs_table": { + "run_type_chips": { + "manual_run": "Ejecución Manual", + "scheduled_run": "Ejecución Programada", + "api": "API", + "unknown_run_type": "Tipo de Ejecución Desconocido" + }, + "run_status_chips": { + "success": "Éxito", + "running": "Ejecutando", + "scheduled": "Programado", + "failed": "Fallido" + }, + "run_settings_modal": { + "title": "Configuración de Ejecución", + "labels": { + "run_id": "ID de Ejecución", + "run_by_user": "Ejecutado por Usuario", + "run_by_schedule": "Ejecutado por ID de Programación", + "run_by_api": "Ejecutado por API", + "run_type": "Tipo de Ejecución" + } + } } } \ No newline at end of file From 0f263978dfde409f490eda5d6758efc71d16283a Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:30:06 +0530 Subject: [PATCH 192/238] feat: add japanese translation for collapsible row --- public/locales/ja.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index f99631eb8..fc31c4637 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -406,5 +406,29 @@ "text": "テキスト: {{text}}" } } + }, + "runs_table": { + "run_type_chips": { + "manual_run": "手動実行", + "scheduled_run": "スケジュール実行", + "api": "API", + "unknown_run_type": "不明な実行タイプ" + }, + "run_status_chips": { + "success": "成功", + "running": "実行中", + "scheduled": "スケジュール済み", + "failed": "失敗" + }, + "run_settings_modal": { + "title": "実行設定", + "labels": { + "run_id": "実行ID", + "run_by_user": "ユーザーによる実行", + "run_by_schedule": "スケジュールによる実行", + "run_by_api": "APIによる実行", + "run_type": "実行タイプ" + } + } } } From 0942e5f17f57200c206c5fd8088a040b825d2fe9 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:30:22 +0530 Subject: [PATCH 193/238] feat: add english translation for collapsible row --- public/locales/en.json | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/public/locales/en.json b/public/locales/en.json index 7176a56e6..111a9391b 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -415,5 +415,29 @@ "text": "テキスト: {{text}}" } } + }, + "runs_table": { + "run_type_chips": { + "manual_run": "Manual Run", + "scheduled_run": "Scheduled Run", + "api": "API", + "unknown_run_type": "Unknown Run Type" + }, + "run_status_chips": { + "success": "Success", + "running": "Running", + "scheduled": "Scheduled", + "failed": "Failed" + }, + "run_settings_modal": { + "title": "Run Settings", + "labels": { + "run_id": "Run ID", + "run_by_user": "Run by User", + "run_by_schedule": "Run by Schedule ID", + "run_by_api": "Run by API", + "run_type": "Run Type" + } + } } - } \ No newline at end of file +} \ No newline at end of file From e83737c80673c7eeab94ae8b46ac1356c77b49b9 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:30:45 +0530 Subject: [PATCH 194/238] feat: add translation for collapsible row --- src/components/molecules/ColapsibleRow.tsx | 46 +++++++++++++++------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/components/molecules/ColapsibleRow.tsx b/src/components/molecules/ColapsibleRow.tsx index 95b144d75..5e4be9da6 100644 --- a/src/components/molecules/ColapsibleRow.tsx +++ b/src/components/molecules/ColapsibleRow.tsx @@ -10,6 +10,7 @@ import { RunContent } from "./RunContent"; import { GenericModal } from "../atoms/GenericModal"; import { modalStyle } from "./AddWhereCondModal"; import { getUserById } from "../../api/auth"; +import { useTranslation } from "react-i18next"; interface RunTypeChipProps { runByUserId?: string; @@ -18,10 +19,12 @@ interface RunTypeChipProps { } const RunTypeChip: React.FC = ({ runByUserId, runByScheduledId, runByAPI }) => { - if (runByUserId) return ; - if (runByScheduledId) return ; - if (runByAPI) return ; - return ; + const { t } = useTranslation(); + + if (runByUserId) return ; + if (runByScheduledId) return ; + if (runByAPI) return ; + return ; }; interface CollapsibleRowProps { @@ -33,6 +36,7 @@ interface CollapsibleRowProps { runningRecordingName: string; } export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRunHandler, runningRecordingName }: CollapsibleRowProps) => { + const { t } = useTranslation(); const [open, setOpen] = useState(isOpen); const [openSettingsModal, setOpenSettingsModal] = useState(false); const [userEmail, setUserEmail] = useState(null); @@ -99,12 +103,12 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRun } else { switch (column.id) { case 'runStatus': - return ( + return ( - {row.status === 'success' && } - {row.status === 'running' && } - {row.status === 'scheduled' && } - {row.status === 'failed' && } + {row.status === 'success' && } + {row.status === 'running' && } + {row.status === 'scheduled' && } + {row.status === 'failed' && } ) case 'delete': @@ -133,21 +137,35 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRun modalStyle={modalStyle} > <> - Run Settings + + {t('runs_table.run_settings_modal.title')} + - Run Type: - + + {t('runs_table.run_settings_modal.labels.run_type')}: + + From defc426466ac5fcea547ed7bae1e90431828771c Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:38:20 +0530 Subject: [PATCH 195/238] feat: add english translation for run content --- public/locales/en.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/public/locales/en.json b/public/locales/en.json index 111a9391b..232a8279b 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -439,5 +439,25 @@ "run_type": "Run Type" } } + }, + "run_content": { + "tabs": { + "output_data": "Output Data", + "log": "Log" + }, + "empty_output": "The output is empty.", + "captured_data": { + "title": "Captured Data", + "download_json": "Download as JSON", + "download_csv": "Download as CSV" + }, + "captured_screenshot": { + "title": "Captured Screenshot", + "download": "Download Screenshot", + "render_failed": "The image failed to render" + }, + "buttons": { + "stop": "Stop" + } } } \ No newline at end of file From 873a0d6df6955474ed02739c27a6133bbced56c7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:38:33 +0530 Subject: [PATCH 196/238] feat: add japanese translation for run content --- public/locales/ja.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/public/locales/ja.json b/public/locales/ja.json index fc31c4637..265632158 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -430,5 +430,25 @@ "run_type": "実行タイプ" } } + }, + "run_content": { + "tabs": { + "output_data": "出力データ", + "log": "ログ" + }, + "empty_output": "出力は空です。", + "captured_data": { + "title": "キャプチャされたデータ", + "download_json": "JSONとしてダウンロード", + "download_csv": "CSVとしてダウンロード" + }, + "captured_screenshot": { + "title": "キャプチャされたスクリーンショット", + "download": "スクリーンショットをダウンロード", + "render_failed": "画像のレンダリングに失敗しました" + }, + "buttons": { + "stop": "停止" + } } } From 4ddf7e8a2970c0b4880e6ab6d673a44429d6ba03 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:39:05 +0530 Subject: [PATCH 197/238] feat: add spanish\ translation for run content --- public/locales/es.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index 24dcad09a..f7a40e86b 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -430,5 +430,25 @@ "run_type": "Tipo de Ejecución" } } + }, + "run_content": { + "tabs": { + "output_data": "Datos de Salida", + "log": "Registro" + }, + "empty_output": "La salida está vacía.", + "captured_data": { + "title": "Datos Capturados", + "download_json": "Descargar como JSON", + "download_csv": "Descargar como CSV" + }, + "captured_screenshot": { + "title": "Captura de Pantalla", + "download": "Descargar Captura", + "render_failed": "No se pudo renderizar la imagen" + }, + "buttons": { + "stop": "Detener" + } } } \ No newline at end of file From c9414fc1c283d0b1fed7ec742f5f9488f069fd85 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:41:22 +0530 Subject: [PATCH 198/238] feat: add german translation for run content --- public/locales/de.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index d33f413b9..5c86d757f 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -429,5 +429,25 @@ "run_type": "Ausführungstyp" } } + }, + "run_content": { + "tabs": { + "output_data": "Ausgabedaten", + "log": "Protokoll" + }, + "empty_output": "Die Ausgabe ist leer.", + "captured_data": { + "title": "Erfasste Daten", + "download_json": "Als JSON herunterladen", + "download_csv": "Als CSV herunterladen" + }, + "captured_screenshot": { + "title": "Erfasster Screenshot", + "download": "Screenshot herunterladen", + "render_failed": "Das Bild konnte nicht gerendert werden" + }, + "buttons": { + "stop": "Stoppen" + } } } From e1ff7f273d62852a2117117c792498412e2d7353 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:41:35 +0530 Subject: [PATCH 199/238] feat: add chinese translation for run content --- public/locales/zh.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 7fc99df06..4f56bd2ca 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -430,5 +430,25 @@ "run_type": "运行类型" } } + }, + "run_content": { + "tabs": { + "output_data": "输出数据", + "log": "日志" + }, + "empty_output": "输出为空。", + "captured_data": { + "title": "捕获的数据", + "download_json": "下载为JSON", + "download_csv": "下载为CSV" + }, + "captured_screenshot": { + "title": "捕获的截图", + "download": "下载截图", + "render_failed": "图像渲染失败" + }, + "buttons": { + "stop": "停止" + } } } \ No newline at end of file From 2df45325e0c1a58553143a591cd31c718d34c4c0 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 17:41:53 +0530 Subject: [PATCH 200/238] feat: add translation for run content --- src/components/molecules/RunContent.tsx | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/molecules/RunContent.tsx b/src/components/molecules/RunContent.tsx index ff414628e..dff44c6cb 100644 --- a/src/components/molecules/RunContent.tsx +++ b/src/components/molecules/RunContent.tsx @@ -13,6 +13,7 @@ import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import 'highlight.js/styles/github.css'; +import { useTranslation } from "react-i18next"; interface RunContentProps { row: Data, @@ -23,6 +24,7 @@ interface RunContentProps { } export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRef, abortRunHandler }: RunContentProps) => { + const { t } = useTranslation(); const [tab, setTab] = React.useState('log'); const [tableData, setTableData] = useState([]); const [columns, setColumns] = useState([]); @@ -76,8 +78,8 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe setTab(newTab)} aria-label="run-content-tabs"> - - + + @@ -102,32 +104,32 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe color="error" onClick={abortRunHandler} > - Stop + {t('run_content.buttons.stop')} : null} {!row || !row.serializableOutput || !row.binaryOutput || (Object.keys(row.serializableOutput).length === 0 && Object.keys(row.binaryOutput).length === 0) - ? The output is empty. : null} + ? {t('run_content.empty_output')} : null} {row.serializableOutput && Object.keys(row.serializableOutput).length !== 0 &&
- Captured Data + {t('run_content.captured_data.title')} - Download as JSON + {t('run_content.captured_data.download_json')} - Download as CSV + {t('run_content.captured_data.download_csv')} {tableData.length > 0 ? ( @@ -171,7 +173,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe
- Captured Screenshot + {t('run_content.captured_screenshot.title')} {Object.keys(row.binaryOutput).map((key) => { try { @@ -181,7 +183,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe width: 'max-content', }}> - Download Screenshot + {t('run_content.captured_screenshot.download')} {key} @@ -189,7 +191,7 @@ export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRe } catch (e) { console.log(e) return - {key}: The image failed to render + {key}: {t('run_content.captured_screenshot.render_failed')} } })} From 72d855261f634d7e69c753df3d3113747f28351a Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:23:59 +0530 Subject: [PATCH 201/238] fix: missing <> --- src/components/molecules/NavBar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 31355b124..d91bde061 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -116,6 +116,7 @@ export const NavBar: React.FC = ({ }, []); return ( + <>
Date: Sat, 21 Dec 2024 18:34:55 +0530 Subject: [PATCH 202/238] feat: language dropdown --- src/components/molecules/NavBar.tsx | 142 +++++++++++++++++++++++++++- 1 file changed, 137 insertions(+), 5 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index d91bde061..4a98f2dda 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -6,7 +6,7 @@ import styled from "styled-components"; import { stopRecording } from "../../api/recording"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { IconButton, Menu, MenuItem, Typography, Chip, Button, Modal, Tabs, Tab, Box, Snackbar } from "@mui/material"; -import { AccountCircle, Logout, Clear, YouTube, X, Update, Close,Language } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../molecules/SaveRecording'; @@ -29,7 +29,7 @@ export const NavBar: React.FC = ({ const { state, dispatch } = useContext(AuthContext); const { user } = state; const navigate = useNavigate(); - const { t, i18n } = useTranslation(); // Get translation function and i18n methods + const { t, i18n } = useTranslation(); const [anchorEl, setAnchorEl] = useState(null); @@ -297,9 +297,141 @@ export const NavBar: React.FC = ({ )} -
- ) : "" - } + + {t("language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("ar"); + handleMenuClose(); + }} + > + العربية + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + +
+ ) : ( + <> + {t("language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("ar"); + handleMenuClose(); + }} + > + العربية + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + + )} ); From f5f17ba8e26be5366da72d130b0de50ed80b889d Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:35:08 +0530 Subject: [PATCH 203/238] chore: lint --- src/components/molecules/NavBar.tsx | 266 ++++++++++++++-------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 4a98f2dda..7f49519dd 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -297,141 +297,141 @@ export const NavBar: React.FC = ({ )} - - {t("language")} - - - { - changeLanguage("en"); - handleMenuClose(); + + {t("language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("ar"); + handleMenuClose(); + }} + > + العربية + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + +
+ ) : ( + <> - English - - { - changeLanguage("es"); - handleMenuClose(); - }} - > - Español - - { - changeLanguage("ja"); - handleMenuClose(); - }} - > - 日本語 - - { - changeLanguage("ar"); - handleMenuClose(); - }} - > - العربية - - { - changeLanguage("zh"); - handleMenuClose(); - }} - > - 中文 - -
- - ) : ( - <> - {t("language")} - - - { - changeLanguage("en"); - handleMenuClose(); - }} - > - English - - { - changeLanguage("es"); - handleMenuClose(); - }} - > - Español - - { - changeLanguage("ja"); - handleMenuClose(); - }} - > - 日本語 - - { - changeLanguage("ar"); - handleMenuClose(); - }} - > - العربية - - { - changeLanguage("zh"); - handleMenuClose(); - }} - > - 中文 - - - )} + {t("language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("ar"); + handleMenuClose(); + }} + > + العربية + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + + )} ); From c551cc1c3271ab924c192d7bb6d9d5adc26aff5d Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:35:33 +0530 Subject: [PATCH 204/238] feat: remove ar --- src/components/molecules/NavBar.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 7f49519dd..7b3da8d51 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -346,14 +346,6 @@ export const NavBar: React.FC = ({ > 日本語 - { - changeLanguage("ar"); - handleMenuClose(); - }} - > - العربية - { changeLanguage("zh"); From af57c196fd7db8d5ec1ea41dff13fef2ca7b2d4c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:35:47 +0530 Subject: [PATCH 205/238] feat: remove ar --- src/components/molecules/NavBar.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 7b3da8d51..271c8e801 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -406,14 +406,6 @@ export const NavBar: React.FC = ({ > 日本語 - { - changeLanguage("ar"); - handleMenuClose(); - }} - > - العربية - { changeLanguage("zh"); From 5c4498ce51201e1f7fb244c1d56a2183cfb294c1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:42:11 +0530 Subject: [PATCH 206/238] feat: add german in dropdown --- src/components/molecules/NavBar.tsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 271c8e801..7c9604c5d 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -354,6 +354,14 @@ export const NavBar: React.FC = ({ > 中文 + { + changeLanguage("de"); + handleMenuClose(); + }} + > + Deutsch + ) : ( @@ -414,6 +422,14 @@ export const NavBar: React.FC = ({ > 中文 + { + changeLanguage("de"); + handleMenuClose(); + }} + > + Deutsch + )} From d17df0eb1776c5d831a6924ee658ff13f8743253 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:42:56 +0530 Subject: [PATCH 207/238] chore: -rm whitespace --- src/components/molecules/NavBar.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 7c9604c5d..33b87f0b9 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -1,5 +1,4 @@ import { useTranslation } from "react-i18next"; - import React, { useState, useContext, useEffect } from 'react'; import axios from 'axios'; import styled from "styled-components"; From e3f3dafe83afa8cbd60bc27045fbb294d1033734 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:43:16 +0530 Subject: [PATCH 208/238] chore: -rm Language icon --- src/components/molecules/NavBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 33b87f0b9..355e65793 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -5,7 +5,7 @@ import styled from "styled-components"; import { stopRecording } from "../../api/recording"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { IconButton, Menu, MenuItem, Typography, Chip, Button, Modal, Tabs, Tab, Box, Snackbar } from "@mui/material"; -import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, YouTube, X, Update, Close } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../molecules/SaveRecording'; From f102b6cf03b7f659116c9182c45a68adfff79f05 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 21 Dec 2024 18:46:43 +0530 Subject: [PATCH 209/238] feat: bring back update button --- src/components/molecules/NavBar.tsx | 45 ++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 355e65793..d011b85f2 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -67,7 +67,6 @@ export const NavBar: React.FC = ({ setTab(newValue); }; - const handleMenuOpen = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; @@ -116,6 +115,50 @@ export const NavBar: React.FC = ({ return ( <> + {isUpdateAvailable && ( + setIsUpdateAvailable(false)} + message={ + `New version ${latestVersion} available! Click "Upgrade" to update.` + } + action={ + <> + + setIsUpdateAvailable(false)} + style={{ color: 'black' }} + > + + + + } + ContentProps={{ + sx: { + background: "white", + color: "black", + } + }} + /> + + )}
Date: Sat, 21 Dec 2024 18:47:05 +0530 Subject: [PATCH 210/238] chore: whitespace --- src/components/molecules/NavBar.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index d011b85f2..5d083de1f 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -157,7 +157,6 @@ export const NavBar: React.FC = ({ } }} /> - )}
Date: Sat, 21 Dec 2024 18:56:04 +0530 Subject: [PATCH 211/238] feat: move lang dropdown inside account settings --- src/components/molecules/NavBar.tsx | 53 +++++++++++++---------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 5d083de1f..6dd5a366d 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -5,7 +5,7 @@ import styled from "styled-components"; import { stopRecording } from "../../api/recording"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { IconButton, Menu, MenuItem, Typography, Chip, Button, Modal, Tabs, Tab, Box, Snackbar } from "@mui/material"; -import { AccountCircle, Logout, Clear, YouTube, X, Update, Close } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../molecules/SaveRecording'; @@ -320,36 +320,11 @@ export const NavBar: React.FC = ({ }}> Twiiter (X) - - - ) : ( - <> - - - Discard - - - - )} - - {t("language")} - + {t("Language")} + = ({ Deutsch + + + ) : ( + <> + + + Discard + + + + )}
) : ( <> Date: Sat, 21 Dec 2024 18:56:43 +0530 Subject: [PATCH 212/238] fix: format --- src/components/molecules/NavBar.tsx | 118 ++++++++++++++-------------- 1 file changed, 58 insertions(+), 60 deletions(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 6dd5a366d..8f1d61c7a 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -320,65 +320,63 @@ export const NavBar: React.FC = ({ }}> Twiiter (X) - - {t("Language")} - - - { - changeLanguage("en"); - handleMenuClose(); - }} - > - English - - { - changeLanguage("es"); - handleMenuClose(); - }} - > - Español - - { - changeLanguage("ja"); - handleMenuClose(); - }} - > - 日本語 - - { - changeLanguage("zh"); - handleMenuClose(); - }} - > - 中文 - - { - changeLanguage("de"); - handleMenuClose(); - }} - > - Deutsch - - + + {t("Language")} + + + { + changeLanguage("en"); + handleMenuClose(); + }} + > + English + + { + changeLanguage("es"); + handleMenuClose(); + }} + > + Español + + { + changeLanguage("ja"); + handleMenuClose(); + }} + > + 日本語 + + { + changeLanguage("zh"); + handleMenuClose(); + }} + > + 中文 + + { + changeLanguage("de"); + handleMenuClose(); + }} + > + Deutsch + + ) : ( @@ -409,7 +407,7 @@ export const NavBar: React.FC = ({ marginRight: "10px", }} > - {t("language")} + {t("Language")} Date: Sat, 21 Dec 2024 19:02:53 +0530 Subject: [PATCH 213/238] feat: add lang icon --- src/components/molecules/NavBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 8f1d61c7a..58f2d72db 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -407,7 +407,7 @@ export const NavBar: React.FC = ({ marginRight: "10px", }} > - {t("Language")} + {t("Language")} Date: Sat, 21 Dec 2024 19:03:05 +0530 Subject: [PATCH 214/238] fix: format --- src/components/molecules/NavBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 58f2d72db..994402ffa 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -407,7 +407,7 @@ export const NavBar: React.FC = ({ marginRight: "10px", }} > - {t("Language")} + {t("Language")} Date: Sat, 21 Dec 2024 19:23:43 +0530 Subject: [PATCH 215/238] feat: add chinese translation for navbar --- public/locales/zh.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/public/locales/zh.json b/public/locales/zh.json index 4f56bd2ca..600fd8211 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -450,5 +450,38 @@ "buttons": { "stop": "停止" } + }, + "navbar": { + "project_name": "Maxun", + "upgrade": { + "button": "升级", + "modal": { + "up_to_date": "🎉 您已是最新版本!", + "new_version_available": "新版本已可用:{{version}}。升级到最新版本以获取错误修复、增强和新功能!", + "view_updates": "查看所有新更新", + "view_updates_link": "此处", + "tabs": { + "manual_setup": "手动设置升级", + "docker_setup": "Docker Compose设置升级" + } + } + }, + "menu_items": { + "logout": "退出登录", + "discord": "Discord", + "youtube": "YouTube", + "twitter": "Twitter (X)", + "language": "语言" + }, + "recording": { + "discard": "丢弃" + } + }, + "language_menu": { + "en": "英语", + "es": "西班牙语", + "ja": "日语", + "zh": "中文", + "de": "德语" } } \ No newline at end of file From 529cedeb68550106d9fa4882eb3694fbc57128f8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 19:23:55 +0530 Subject: [PATCH 216/238] feat: add german translation for navbar --- public/locales/de.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 5c86d757f..28855c78c 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -449,5 +449,38 @@ "buttons": { "stop": "Stoppen" } + }, + "navbar": { + "project_name": "Maxun", + "upgrade": { + "button": "Upgrade", + "modal": { + "up_to_date": "🎉 Du bist auf dem neuesten Stand!", + "new_version_available": "Eine neue Version ist verfügbar: {{version}}. Aktualisieren Sie auf die neueste Version für Fehlerkorrekturen, Verbesserungen und neue Funktionen!", + "view_updates": "Alle Updates anzeigen", + "view_updates_link": "hier", + "tabs": { + "manual_setup": "Manuelles Setup-Upgrade", + "docker_setup": "Docker Compose Setup-Upgrade" + } + } + }, + "menu_items": { + "logout": "Abmelden", + "discord": "Discord", + "youtube": "YouTube", + "twitter": "Twitter (X)", + "language": "Sprache" + }, + "recording": { + "discard": "Verwerfen" + } + }, + "language_menu": { + "en": "Englisch", + "es": "Spanisch", + "ja": "Japanisch", + "zh": "Chinesisch", + "de": "Deutsch" } } From 17e0afdbf8650df5081b599bf8f3233fbf25b656 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 19:24:11 +0530 Subject: [PATCH 217/238] feat: add spanish translation for navbar --- public/locales/es.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/public/locales/es.json b/public/locales/es.json index f7a40e86b..4ef417ea6 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -450,5 +450,38 @@ "buttons": { "stop": "Detener" } + }, + "navbar": { + "project_name": "Maxun", + "upgrade": { + "button": "Actualizar", + "modal": { + "up_to_date": "¡Estás actualizado!", + "new_version_available": "Hay una nueva versión disponible: {{version}}. ¡Actualice a la última versión para correcciones de errores, mejoras y nuevas características!", + "view_updates": "Ver todas las actualizaciones", + "view_updates_link": "aquí", + "tabs": { + "manual_setup": "Actualización de Configuración Manual", + "docker_setup": "Actualización de Configuración Docker Compose" + } + } + }, + "menu_items": { + "logout": "Cerrar sesión", + "discord": "Discord", + "youtube": "YouTube", + "twitter": "Twitter (X)", + "language": "Idioma" + }, + "recording": { + "discard": "Descartar" + } + }, + "language_menu": { + "en": "Inglés", + "es": "Español", + "ja": "Japonés", + "zh": "Chino", + "de": "Alemán" } } \ No newline at end of file From 2958453e657b2d19e671bfa13c2e91beb3620888 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 19:24:47 +0530 Subject: [PATCH 218/238] feat: add translation --- public/locales/en.json | 33 +++++++++++++++++++++++++++++ public/locales/ja.json | 33 +++++++++++++++++++++++++++++ src/components/molecules/NavBar.tsx | 24 ++++++++++----------- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/public/locales/en.json b/public/locales/en.json index 232a8279b..8084b5f28 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -459,5 +459,38 @@ "buttons": { "stop": "Stop" } + }, + "navbar": { + "project_name": "Maxun", + "upgrade": { + "button": "Upgrade", + "modal": { + "up_to_date": "🎉 You're up to date!", + "new_version_available": "A new version is available: {{version}}. Upgrade to the latest version for bug fixes, enhancements and new features!", + "view_updates": "View all the new updates", + "view_updates_link": "here", + "tabs": { + "manual_setup": "Manual Setup Upgrade", + "docker_setup": "Docker Compose Setup Upgrade" + } + } + }, + "menu_items": { + "logout": "Logout", + "discord": "Discord", + "youtube": "YouTube", + "twitter": "Twitter (X)", + "language": "Language" + }, + "recording": { + "discard": "Discard" + } + }, + "language_menu": { + "en": "English", + "es": "Spanish", + "ja": "Japanese", + "zh": "Chinese", + "de": "German" } } \ No newline at end of file diff --git a/public/locales/ja.json b/public/locales/ja.json index 265632158..b40cc6e60 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -450,5 +450,38 @@ "buttons": { "stop": "停止" } + }, + "navbar": { + "project_name": "Maxun", + "upgrade": { + "button": "アップグレード", + "modal": { + "up_to_date": "最新版です!", + "new_version_available": "新しいバージョンが利用可能です: {{version}}。バグ修正、機能強化のために最新版にアップグレードしてください。", + "view_updates": "すべての更新を", + "view_updates_link": "こちら", + "tabs": { + "manual_setup": "手動セットアップ", + "docker_setup": "Docker Composeセットアップ" + } + } + }, + "menu_items": { + "logout": "ログアウト", + "discord": "Discord", + "youtube": "YouTube", + "twitter": "Twitter (X)", + "language": "言語" + }, + "recording": { + "discard": "破棄" + } + }, + "language_menu": { + "en": "英語", + "es": "スペイン語", + "ja": "日本語", + "zh": "中国語", + "de": "ドイツ語" } } diff --git a/src/components/molecules/NavBar.tsx b/src/components/molecules/NavBar.tsx index 994402ffa..142d45ab8 100644 --- a/src/components/molecules/NavBar.tsx +++ b/src/components/molecules/NavBar.tsx @@ -120,7 +120,7 @@ export const NavBar: React.FC = ({ open={isUpdateAvailable} onClose={() => setIsUpdateAvailable(false)} message={ - `New version ${latestVersion} available! Click "Upgrade" to update.` + `${t('navbar.upgrade.modal.new_version_available', { version: latestVersion })} ${t('navbar.upgrade.modal.view_updates')}` } action={ <> @@ -137,7 +137,7 @@ export const NavBar: React.FC = ({ borderRadius: '5px', }} > - Upgrade + {t('navbar.upgrade.button')} = ({ justifyContent: 'flex-start', }}> -
Maxun
+
{t('navbar.project_name')}
= ({ border: "#00000099 1px solid", '&:hover': { color: '#ff00c3', border: '#ff00c3 1px solid' } }}> - Upgrade Maxun + {t('navbar.upgrade.button')} Maxun = ({ Checking for updates... ) : currentVersion === latestVersion ? ( - 🎉 You're up to date! + {t('navbar.upgrade.modal.up_to_date')} ) : ( <> - A new version is available: {latestVersion}. Upgrade to the latest version for bug fixes, enhancements and new features! + {t('navbar.upgrade.modal.new_version_available', { version: latestVersion })}
- View all the new updates + {t('navbar.upgrade.modal.view_updates')} {' '}here.
= ({ sx={{ marginTop: 2, marginBottom: 2 }} centered > - - + + {tab === 0 && ( @@ -303,7 +303,7 @@ export const NavBar: React.FC = ({ PaperProps={{ sx: { width: '180px' } }} > { handleMenuClose(); logout(); }}> - Logout + {t('navbar.menu_items.logout')} { window.open('https://discord.gg/5GbPjBUkws', '_blank'); @@ -321,7 +321,7 @@ export const NavBar: React.FC = ({ Twiiter (X) - {t("Language")} + {t('navbar.menu_items.language')} = ({ '&:hover': { color: 'white', backgroundColor: 'red' } }}> - Discard + {t('navbar.recording.discard')} From 2e28f84b12c49880c9cbd831e60870c80abdd2c5 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 20:34:35 +0530 Subject: [PATCH 219/238] feat: add reset button for output preview --- .../molecules/InterpretationLog.tsx | 59 +++++++++++++++++-- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/components/molecules/InterpretationLog.tsx b/src/components/molecules/InterpretationLog.tsx index 0a7715353..4d14bc51f 100644 --- a/src/components/molecules/InterpretationLog.tsx +++ b/src/components/molecules/InterpretationLog.tsx @@ -94,6 +94,12 @@ export const InterpretationLog: React.FC = ({ isOpen, se setCustomValue(event.target.value); }; + const handleReset = () => { + setLog(''); + setTableData([]); + setBinaryData(null); + }; + useEffect(() => { socket?.on('log', handleLog); socket?.on('serializableCallback', handleSerializableCallback); @@ -172,12 +178,34 @@ export const InterpretationLog: React.FC = ({ isOpen, se > { binaryData ? ( -
- - {t('interpretation_log.titles.screenshot')} - - {t('interpretation_log.titles.screenshot')} -
+ <> +
+ + {t('interpretation_log.titles.screenshot')} + + {t('interpretation_log.titles.screenshot')} +
+ + ) : tableData.length > 0 ? ( <> @@ -203,6 +231,25 @@ export const InterpretationLog: React.FC = ({ isOpen, se {t('interpretation_log.messages.additional_rows')} + ) : ( From 8cd5efcac301edb93cad100a0ca474e4962e9436 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 20:35:26 +0530 Subject: [PATCH 220/238] feat: add reset button translation --- public/locales/de.json | 1 + public/locales/en.json | 1 + public/locales/es.json | 1 + public/locales/ja.json | 1 + public/locales/zh.json | 1 + 5 files changed, 5 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 28855c78c..6ea6e509f 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -250,6 +250,7 @@ "interpretation_buttons": { "buttons": { "preview": "Vorschau der Ausgabedaten anzeigen", + "reset": "Zurücksetzen", "yes": "Ja", "no": "Nein" }, diff --git a/public/locales/en.json b/public/locales/en.json index 8084b5f28..0b4f9461c 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -251,6 +251,7 @@ "interpretation_buttons": { "buttons": { "preview": "Get Preview of Output Data", + "reset": "Reset", "yes": "Yes", "no": "No" }, diff --git a/public/locales/es.json b/public/locales/es.json index 4ef417ea6..40ef1d6b8 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -251,6 +251,7 @@ "interpretation_buttons": { "buttons": { "preview": "Obtener Vista Previa de Datos de Salida", + "reset": "Restablecer", "yes": "Sí", "no": "No" }, diff --git a/public/locales/ja.json b/public/locales/ja.json index b40cc6e60..946ae0297 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -251,6 +251,7 @@ "interpretation_buttons": { "buttons": { "preview": "出力データのプレビューを取得", + "reset": "リセット", "yes": "はい", "no": "いいえ" }, diff --git a/public/locales/zh.json b/public/locales/zh.json index 600fd8211..8ec36ddc3 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -251,6 +251,7 @@ "interpretation_buttons": { "buttons": { "preview": "获取输出数据预览", + "reset": "重置", "yes": "是", "no": "否" }, From 74da84a14421e8ecdab6366150e2bd4b26ffc3f7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 21:42:48 +0530 Subject: [PATCH 221/238] feat: add output preview reset notification --- src/components/molecules/InterpretationLog.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/molecules/InterpretationLog.tsx b/src/components/molecules/InterpretationLog.tsx index 4d14bc51f..05e2876ce 100644 --- a/src/components/molecules/InterpretationLog.tsx +++ b/src/components/molecules/InterpretationLog.tsx @@ -35,7 +35,7 @@ export const InterpretationLog: React.FC = ({ isOpen, se const { width } = useBrowserDimensionsStore(); const { socket } = useSocketStore(); - const { currentWorkflowActionsState } = useGlobalInfoStore(); + const { currentWorkflowActionsState, notify } = useGlobalInfoStore(); const toggleDrawer = (newOpen: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => { if ( @@ -98,6 +98,7 @@ export const InterpretationLog: React.FC = ({ isOpen, se setLog(''); setTableData([]); setBinaryData(null); + notify("success", t('interpretation_log.notifications.reset_success')); }; useEffect(() => { From 64f452b4dc1546d4fcaafe041d00c50bfad73ad8 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 21:43:35 +0530 Subject: [PATCH 222/238] feat: add reset success translation --- public/locales/de.json | 3 +++ public/locales/en.json | 3 +++ public/locales/es.json | 3 +++ public/locales/ja.json | 3 +++ public/locales/zh.json | 3 +++ 5 files changed, 15 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 6ea6e509f..90beaa140 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -245,6 +245,9 @@ "mimetype": "Medientyp: ", "image_below": "Bild wird unten angezeigt:", "separator": "--------------------------------------------------" + }, + "notifications": { + "reset_success": "Vorschau erfolgreich zurückgesetzt" } }, "interpretation_buttons": { diff --git a/public/locales/en.json b/public/locales/en.json index 0b4f9461c..7752ad78e 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -246,6 +246,9 @@ "mimetype": "mimetype: ", "image_below": "Image is rendered below:", "separator": "--------------------------------------------------" + }, + "notifications": { + "reset_success": "Output Preview reset successfully" } }, "interpretation_buttons": { diff --git a/public/locales/es.json b/public/locales/es.json index 40ef1d6b8..00fa379ed 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -265,6 +265,9 @@ "use_previous": "¿Desea usar su selección anterior como condición para realizar esta acción?", "previous_action": "Su acción anterior fue: ", "element_text": "en un elemento con texto " + }, + "notifications": { + "reset_success": "Vista previa restablecida correctamente" } }, "recording_page": { diff --git a/public/locales/ja.json b/public/locales/ja.json index 946ae0297..b444c81ab 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -246,6 +246,9 @@ "mimetype": "MIMEタイプ: ", "image_below": "画像は以下に表示されます:", "separator": "--------------------------------------------------" + }, + "notifications": { + "reset_success": "出力プレビューが正常にリセットされました" } }, "interpretation_buttons": { diff --git a/public/locales/zh.json b/public/locales/zh.json index 8ec36ddc3..27455ebe3 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -246,6 +246,9 @@ "mimetype": "MIME类型:", "image_below": "图片显示如下:", "separator": "--------------------------------------------------" + }, + "notifications": { + "reset_success": "输出预览已成功重置" } }, "interpretation_buttons": { From c2b7088b180a6804b36ec2c08e54009b634ff608 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 22:58:23 +0530 Subject: [PATCH 223/238] feat: add context handlers to reset output preview log --- src/context/globalInfo.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/context/globalInfo.tsx b/src/context/globalInfo.tsx index 58589c3a1..ac281630b 100644 --- a/src/context/globalInfo.tsx +++ b/src/context/globalInfo.tsx @@ -32,6 +32,8 @@ interface GlobalInfo { hasScreenshotAction: boolean; hasScrapeSchemaAction: boolean; }) => void; + shouldResetInterpretationLog: boolean; + resetInterpretationLog: () => void; }; class GlobalInfoStore implements Partial { @@ -53,6 +55,7 @@ class GlobalInfoStore implements Partial { hasScreenshotAction: false, hasScrapeSchemaAction: false, }; + shouldResetInterpretationLog = false; }; const globalInfoStore = new GlobalInfoStore(); @@ -71,6 +74,7 @@ export const GlobalInfoProvider = ({ children }: { children: JSX.Element }) => { const [recordingName, setRecordingName] = useState(globalInfoStore.recordingName); const [recordingUrl, setRecordingUrl] = useState(globalInfoStore.recordingUrl); const [currentWorkflowActionsState, setCurrentWorkflowActionsState] = useState(globalInfoStore.currentWorkflowActionsState); + const [shouldResetInterpretationLog, setShouldResetInterpretationLog] = useState(globalInfoStore.shouldResetInterpretationLog); const notify = (severity: 'error' | 'warning' | 'info' | 'success', message: string) => { setNotification({ severity, message, isOpen: true }); @@ -87,6 +91,14 @@ export const GlobalInfoProvider = ({ children }: { children: JSX.Element }) => { } } + const resetInterpretationLog = () => { + setShouldResetInterpretationLog(true); + // Reset the flag after a short delay to allow components to respond + setTimeout(() => { + setShouldResetInterpretationLog(false); + }, 100); + } + return ( { setRecordingUrl, currentWorkflowActionsState, setCurrentWorkflowActionsState, + shouldResetInterpretationLog, + resetInterpretationLog, }} > {children} From e16d1a1c113b8066a882532422b8d9c001cd660d Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 22:59:54 +0530 Subject: [PATCH 224/238] feat: add reset interpretation context action on confirm text data --- src/components/organisms/RightSidePanel.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/organisms/RightSidePanel.tsx b/src/components/organisms/RightSidePanel.tsx index 224e0954e..ba178b7bd 100644 --- a/src/components/organisms/RightSidePanel.tsx +++ b/src/components/organisms/RightSidePanel.tsx @@ -57,7 +57,7 @@ export const RightSidePanel: React.FC = ({ onFinishCapture const [hoverStates, setHoverStates] = useState<{ [id: string]: boolean }>({}); const [browserStepIdList, setBrowserStepIdList] = useState([]); - const { lastAction, notify, currentWorkflowActionsState, setCurrentWorkflowActionsState } = useGlobalInfoStore(); + const { lastAction, notify, currentWorkflowActionsState, setCurrentWorkflowActionsState, resetInterpretationLog } = useGlobalInfoStore(); const { getText, startGetText, stopGetText, getScreenshot, startGetScreenshot, stopGetScreenshot, getList, startGetList, stopGetList, startPaginationMode, stopPaginationMode, paginationType, updatePaginationType, limitType, customLimit, updateLimitType, updateCustomLimit, stopLimitMode, startLimitMode, captureStage, setCaptureStage } = useActionContext(); const { browserSteps, updateBrowserTextStepLabel, deleteBrowserStep, addScreenshotStep, updateListTextFieldLabel, removeListTextField } = useBrowserSteps(); const { id, socket } = useSocketStore(); @@ -225,8 +225,9 @@ export const RightSidePanel: React.FC = ({ onFinishCapture if (hasTextSteps) { socket?.emit('action', { action: 'scrapeSchema', settings }); } + resetInterpretationLog(); onFinishCapture(); - }, [stopGetText, getTextSettingsObject, socket, browserSteps, confirmedTextSteps]); + }, [stopGetText, getTextSettingsObject, socket, browserSteps, confirmedTextSteps, resetInterpretationLog]); const getListSettingsObject = useCallback(() => { let settings: { From fb7fafbae6a9cb2742a25f724db60ca5c309051b Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 23:02:15 +0530 Subject: [PATCH 225/238] feat: rm reset button for output preview --- .../molecules/InterpretationLog.tsx | 53 +++---------------- 1 file changed, 6 insertions(+), 47 deletions(-) diff --git a/src/components/molecules/InterpretationLog.tsx b/src/components/molecules/InterpretationLog.tsx index 05e2876ce..99b9fc8b9 100644 --- a/src/components/molecules/InterpretationLog.tsx +++ b/src/components/molecules/InterpretationLog.tsx @@ -179,34 +179,12 @@ export const InterpretationLog: React.FC = ({ isOpen, se > { binaryData ? ( - <> -
- - {t('interpretation_log.titles.screenshot')} - - {t('interpretation_log.titles.screenshot')} -
- - +
+ + {t('interpretation_log.titles.screenshot')} + + {t('interpretation_log.titles.screenshot')} +
) : tableData.length > 0 ? ( <> @@ -232,25 +210,6 @@ export const InterpretationLog: React.FC = ({ isOpen, se {t('interpretation_log.messages.additional_rows')} - ) : ( From 827e5ecbafbeff21879286a3459217b7eff536b7 Mon Sep 17 00:00:00 2001 From: RohitR311 Date: Sat, 21 Dec 2024 23:04:44 +0530 Subject: [PATCH 226/238] feat: reset data based on current interpretation log state --- src/components/molecules/InterpretationLog.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/components/molecules/InterpretationLog.tsx b/src/components/molecules/InterpretationLog.tsx index 99b9fc8b9..227e621c2 100644 --- a/src/components/molecules/InterpretationLog.tsx +++ b/src/components/molecules/InterpretationLog.tsx @@ -35,7 +35,7 @@ export const InterpretationLog: React.FC = ({ isOpen, se const { width } = useBrowserDimensionsStore(); const { socket } = useSocketStore(); - const { currentWorkflowActionsState, notify } = useGlobalInfoStore(); + const { currentWorkflowActionsState, shouldResetInterpretationLog, notify } = useGlobalInfoStore(); const toggleDrawer = (newOpen: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => { if ( @@ -94,12 +94,13 @@ export const InterpretationLog: React.FC = ({ isOpen, se setCustomValue(event.target.value); }; - const handleReset = () => { - setLog(''); - setTableData([]); - setBinaryData(null); - notify("success", t('interpretation_log.notifications.reset_success')); - }; + useEffect(() => { + if (shouldResetInterpretationLog) { + setLog(''); + setTableData([]); + setBinaryData(null); + } + }, [shouldResetInterpretationLog]); useEffect(() => { socket?.on('log', handleLog); From fee13e7fefdc91e23a72f7d78cd61305fd722f9f Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 22 Dec 2024 22:05:45 +0530 Subject: [PATCH 227/238] feat: gracefully proceed if !adblocker --- .../browser-management/classes/RemoteBrowser.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/server/src/browser-management/classes/RemoteBrowser.ts b/server/src/browser-management/classes/RemoteBrowser.ts index 31aceadaa..2c45d1463 100644 --- a/server/src/browser-management/classes/RemoteBrowser.ts +++ b/server/src/browser-management/classes/RemoteBrowser.ts @@ -245,10 +245,17 @@ export class RemoteBrowser { await this.setupPageEventListeners(this.currentPage); - const blocker = await PlaywrightBlocker.fromLists(fetch, ['https://easylist.to/easylist/easylist.txt']); - await blocker.enableBlockingInPage(this.currentPage); - this.client = await this.currentPage.context().newCDPSession(this.currentPage); - await blocker.disableBlockingInPage(this.currentPage); + try { + const blocker = await PlaywrightBlocker.fromLists(fetch, ['https://easylist.to/easylist/easylist.txt']); + await blocker.enableBlockingInPage(this.currentPage); + this.client = await this.currentPage.context().newCDPSession(this.currentPage); + await blocker.disableBlockingInPage(this.currentPage); + console.log('Adblocker initialized'); + } catch (error: any) { + console.warn('Failed to initialize adblocker, continuing without it:', error.message); + // Still need to set up the CDP session even if blocker fails + this.client = await this.currentPage.context().newCDPSession(this.currentPage); + } }; /** From 584433e3f775f44c705c6e2a9152d77d006635fb Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 22 Dec 2024 22:08:56 +0530 Subject: [PATCH 228/238] feat: try-catch handling for adblocker in core --- maxun-core/src/interpret.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/maxun-core/src/interpret.ts b/maxun-core/src/interpret.ts index 14d8f46e2..bc99c92f5 100644 --- a/maxun-core/src/interpret.ts +++ b/maxun-core/src/interpret.ts @@ -111,13 +111,21 @@ export default class Interpreter extends EventEmitter { private async applyAdBlocker(page: Page): Promise { if (this.blocker) { - await this.blocker.enableBlockingInPage(page); + try { + await this.blocker.enableBlockingInPage(page); + } catch (err) { + this.log(`Ad-blocker operation failed:`, Level.ERROR); + } } } private async disableAdBlocker(page: Page): Promise { if (this.blocker) { - await this.blocker.disableBlockingInPage(page); + try { + await this.blocker.disableBlockingInPage(page); + } catch (err) { + this.log(`Ad-blocker operation failed:`, Level.ERROR); + } } } From 58f92a35dc6eace6b58f095678a684c886da91b3 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:03:20 +0530 Subject: [PATCH 229/238] feat: try-catch handling for adblocker in core --- maxun-core/src/interpret.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/maxun-core/src/interpret.ts b/maxun-core/src/interpret.ts index bc99c92f5..c581954df 100644 --- a/maxun-core/src/interpret.ts +++ b/maxun-core/src/interpret.ts @@ -670,7 +670,11 @@ export default class Interpreter extends EventEmitter { const workflowCopy: Workflow = JSON.parse(JSON.stringify(workflow)); // apply ad-blocker to the current page - await this.applyAdBlocker(p); + try { + await this.applyAdBlocker(p); + } catch (error) { + this.log(`Failed to apply ad-blocker: ${error.message}`, Level.ERROR); + } const usedActions: string[] = []; let selectors: string[] = []; let lastAction = null; From d016900237505c0d0180111c9bcd7e671ef3237c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:18:33 +0530 Subject: [PATCH 230/238] chore: 0.0.7 maxun-core --- maxun-core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maxun-core/package.json b/maxun-core/package.json index 36d06aa92..7c92d08e0 100644 --- a/maxun-core/package.json +++ b/maxun-core/package.json @@ -1,6 +1,6 @@ { "name": "maxun-core", - "version": "0.0.6", + "version": "0.0.7", "description": "Core package for Maxun, responsible for data extraction", "main": "build/index.js", "typings": "build/index.d.ts", From 470eaa80f10d8413db9a2c577d9378ea0ca6733f Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:21:48 +0530 Subject: [PATCH 231/238] chore: maxun v0.0.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 866c3dd2f..c09002082 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "maxun", - "version": "0.0.4", + "version": "0.0.5", "author": "Maxun", "license": "AGPL-3.0-or-later", "dependencies": { From 58ab253382debd8f31585123a228f639bbb77456 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:22:13 +0530 Subject: [PATCH 232/238] chore: lint --- package.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index c09002082..21ea30959 100644 --- a/package.json +++ b/package.json @@ -36,13 +36,10 @@ "fortawesome": "^0.0.1-security", "google-auth-library": "^9.14.1", "googleapis": "^144.0.0", - "i18next": "^24.0.2", "i18next-browser-languagedetector": "^8.0.0", "i18next-http-backend": "^3.0.1", - "idcac-playwright": "^0.1.3", - "ioredis": "^5.4.1", "joi": "^17.6.0", "jsonwebtoken": "^9.0.2", @@ -118,4 +115,4 @@ "ts-node": "^10.4.0", "vite": "^5.4.10" } -} +} \ No newline at end of file From 13b15db8c29f747b59fae1bf5e4a5da6a9432c96 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:24:12 +0530 Subject: [PATCH 233/238] chore: 0.0.7 maxun-core --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 21ea30959..e89f13de1 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "jwt-decode": "^4.0.0", "loglevel": "^1.8.0", "loglevel-plugin-remote": "^0.6.8", - "maxun-core": "^0.0.6", + "maxun-core": "^0.0.7", "minio": "^8.0.1", "moment-timezone": "^0.5.45", "node-cron": "^3.0.3", @@ -115,4 +115,4 @@ "ts-node": "^10.4.0", "vite": "^5.4.10" } -} \ No newline at end of file +} From e6da1350ee395ee3fa031ff6ab62a6d5adee55a0 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:25:26 +0530 Subject: [PATCH 234/238] temp: pass --legacy-peer-deps for i18n --- Dockerfile | 2 +- server/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 032dc9823..352d4e408 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ COPY package*.json ./ COPY maxun-core ./maxun-core # Install dependencies -RUN npm install +RUN npm install --legacy-peer-deps # Copy frontend source code and config COPY src ./src diff --git a/server/Dockerfile b/server/Dockerfile index e738f2521..a764058ae 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -13,7 +13,7 @@ COPY server/tsconfig.json ./server/ # COPY server/start.sh ./ # Install dependencies -RUN npm install +RUN npm install --legacy-peer-deps # Install Playwright browsers and dependencies RUN npx playwright install --with-deps chromium From 72e219015ad6bdf6d1e004722a3bec5e039f26a9 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 00:26:42 +0530 Subject: [PATCH 235/238] chore: frontend 0.0.4, backend 0.0.8 --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3c6e3a0f7..5a5b8eae0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,7 +43,7 @@ services: #build: #context: . #dockerfile: server/Dockerfile - image: getmaxun/maxun-backend:v0.0.7 + image: getmaxun/maxun-backend:v0.0.8 ports: - "${BACKEND_PORT:-8080}:${BACKEND_PORT:-8080}" env_file: .env @@ -70,7 +70,7 @@ services: #build: #context: . #dockerfile: Dockerfile - image: getmaxun/maxun-frontend:v0.0.3 + image: getmaxun/maxun-frontend:v0.0.4 ports: - "${FRONTEND_PORT:-5173}:${FRONTEND_PORT:-5173}" env_file: .env From 73006804ba43b2314d6e16559226cfe057a7ea20 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 01:15:00 +0530 Subject: [PATCH 236/238] chore: copy public folder --- server/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/server/Dockerfile b/server/Dockerfile index a764058ae..7e197fd37 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -7,6 +7,7 @@ WORKDIR /app COPY package*.json ./ COPY maxun-core ./maxun-core COPY src ./src +COPY public ./public COPY server ./server COPY tsconfig.json ./ COPY server/tsconfig.json ./server/ From 26ca043c23cef908ad8f1c820c9d25076b1f3038 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 01:15:11 +0530 Subject: [PATCH 237/238] chore: copy public folder --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 352d4e408..33df05e98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,7 @@ RUN npm install --legacy-peer-deps # Copy frontend source code and config COPY src ./src +COPY public ./public COPY index.html ./ COPY vite.config.js ./ COPY tsconfig.json ./ From 4ac55f076857efed0807d2079efa0213e09fb04b Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 23 Dec 2024 01:15:45 +0530 Subject: [PATCH 238/238] feat: backend 0.0.9, frontend 0.0.5 --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5a5b8eae0..874e48d60 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,7 +43,7 @@ services: #build: #context: . #dockerfile: server/Dockerfile - image: getmaxun/maxun-backend:v0.0.8 + image: getmaxun/maxun-backend:v0.0.9 ports: - "${BACKEND_PORT:-8080}:${BACKEND_PORT:-8080}" env_file: .env @@ -70,7 +70,7 @@ services: #build: #context: . #dockerfile: Dockerfile - image: getmaxun/maxun-frontend:v0.0.4 + image: getmaxun/maxun-frontend:v0.0.5 ports: - "${FRONTEND_PORT:-5173}:${FRONTEND_PORT:-5173}" env_file: .env