From f3d49f175cd9586d7e060704014e5d70be668fe1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:09:24 +0530 Subject: [PATCH 001/138] chore: remove unused import --- src/components/integration/IntegrationSettings.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/integration/IntegrationSettings.tsx b/src/components/integration/IntegrationSettings.tsx index f9c397ae..835221ca 100644 --- a/src/components/integration/IntegrationSettings.tsx +++ b/src/components/integration/IntegrationSettings.tsx @@ -14,7 +14,6 @@ import axios from "axios"; 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"; From 60c536d4bfcc9e785646dd5694de5b0d30bcb92f Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:10:04 +0530 Subject: [PATCH 002/138] chore: remove unused import --- src/components/recorder/AddWhatCondModal.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/recorder/AddWhatCondModal.tsx b/src/components/recorder/AddWhatCondModal.tsx index a6b50fc9..4dd333b5 100644 --- a/src/components/recorder/AddWhatCondModal.tsx +++ b/src/components/recorder/AddWhatCondModal.tsx @@ -3,7 +3,6 @@ import { GenericModal } from "../ui/GenericModal"; import { modalStyle } from "./AddWhereCondModal"; import { Button, MenuItem, TextField, Typography } from "@mui/material"; import React, { useRef } from "react"; -import { Dropdown as MuiDropdown } from "../ui/DropdownMui"; import { KeyValueForm } from "./KeyValueForm"; import { ClearButton } from "../ui/buttons/ClearButton"; import { useSocketStore } from "../../context/socket"; From 0fd12774c462189ef4d01926616ae9edab0b1b38 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:10:29 +0530 Subject: [PATCH 003/138] chore: remove unused import --- src/components/recorder/canvas.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/recorder/canvas.tsx b/src/components/recorder/canvas.tsx index 83e48274..cc75a6ba 100644 --- a/src/components/recorder/canvas.tsx +++ b/src/components/recorder/canvas.tsx @@ -1,6 +1,5 @@ import React, { useCallback, useEffect, useRef } from 'react'; import { useSocketStore } from '../../context/socket'; -import { getMappedCoordinates } from "../../helpers/inputHelpers"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { useActionContext } from '../../context/browserActions'; import DatePicker from '../pickers/DatePicker'; From 94a6fc8b70ebcf6b5c59c64164a4ba113d063093 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:10:53 +0530 Subject: [PATCH 004/138] fix: whitespace --- src/components/recorder/Highlighter.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/recorder/Highlighter.tsx b/src/components/recorder/Highlighter.tsx index 3771b149..562fd81e 100644 --- a/src/components/recorder/Highlighter.tsx +++ b/src/components/recorder/Highlighter.tsx @@ -1,5 +1,4 @@ import React from 'react'; - import styled from "styled-components"; interface HighlighterProps { From 7ced40d94c8e776753aa9516fa39d0eb38c4dba4 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:11:24 +0530 Subject: [PATCH 005/138] fix: whitespace --- src/components/recorder/LeftSidePanel.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/recorder/LeftSidePanel.tsx b/src/components/recorder/LeftSidePanel.tsx index afe56ffe..939f0329 100644 --- a/src/components/recorder/LeftSidePanel.tsx +++ b/src/components/recorder/LeftSidePanel.tsx @@ -3,7 +3,6 @@ import React, { useCallback, useEffect, useState } from "react"; import { getActiveWorkflow, getParamsOfActiveWorkflow } from "../../api/workflow"; import { useSocketStore } from '../../context/socket'; import { WhereWhatPair, WorkflowFile } from "maxun-core"; -import { SidePanelHeader } from "./SidePanelHeader"; import { emptyWorkflow } from "../../shared/constants"; import { LeftSidePanelContent } from "./LeftSidePanelContent"; import { useBrowserDimensionsStore } from "../../context/browserDimensions"; From fba1b420a312250e9e7e05374e6f8aab39cba701 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:11:49 +0530 Subject: [PATCH 006/138] chore: remove unused import --- src/components/recorder/LeftSidePanelContent.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/recorder/LeftSidePanelContent.tsx b/src/components/recorder/LeftSidePanelContent.tsx index 4a980505..745e0e31 100644 --- a/src/components/recorder/LeftSidePanelContent.tsx +++ b/src/components/recorder/LeftSidePanelContent.tsx @@ -1,15 +1,13 @@ import React, { useCallback, useEffect, useState } from 'react'; -import Box from "@mui/material/Box"; import { Pair } from "./Pair"; import { WhereWhatPair, WorkflowFile } from "maxun-core"; import { useSocketStore } from "../../context/socket"; -import { Add } from "@mui/icons-material"; import { Socket } from "socket.io-client"; import { AddButton } from "../ui/buttons/AddButton"; import { AddPair } from "../../api/workflow"; import { GenericModal } from "../ui/GenericModal"; import { PairEditForm } from "./PairEditForm"; -import { Fab, Tooltip, Typography } from "@mui/material"; +import { Tooltip } from "@mui/material"; interface LeftSidePanelContentProps { workflow: WorkflowFile; From cb68fbb8bac343a3ccdaf05eb173242582be594a Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:12:24 +0530 Subject: [PATCH 007/138] chore: remove unused import --- src/components/recorder/PairDetail.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/recorder/PairDetail.tsx b/src/components/recorder/PairDetail.tsx index d330db1d..7ed081a9 100644 --- a/src/components/recorder/PairDetail.tsx +++ b/src/components/recorder/PairDetail.tsx @@ -1,6 +1,6 @@ import React, { useLayoutEffect, useRef, useState } from 'react'; import { WhereWhatPair } from "maxun-core"; -import { Box, Button, IconButton, MenuItem, Stack, TextField, Tooltip, Typography } from "@mui/material"; +import { IconButton, Stack, TextField, Tooltip, Typography } from "@mui/material"; import { Close, KeyboardArrowDown, KeyboardArrowUp } from "@mui/icons-material"; import TreeView from '@mui/lab/TreeView'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; @@ -11,7 +11,6 @@ import { WarningText } from "../ui/texts"; import NotificationImportantIcon from '@mui/icons-material/NotificationImportant'; import { RemoveButton } from "../ui/buttons/RemoveButton"; import { AddWhereCondModal } from "./AddWhereCondModal"; -import { UpdatePair } from "../../api/workflow"; import { useSocketStore } from "../../context/socket"; import { AddWhatCondModal } from "./AddWhatCondModal"; From 421103dcfcdd4cb8a1f783572b6dcba8ac0d4011 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:13:10 +0530 Subject: [PATCH 008/138] chore: remove unused import --- src/components/recorder/RightSidePanel.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/recorder/RightSidePanel.tsx b/src/components/recorder/RightSidePanel.tsx index deb45ff9..f324183d 100644 --- a/src/components/recorder/RightSidePanel.tsx +++ b/src/components/recorder/RightSidePanel.tsx @@ -3,7 +3,6 @@ import { Button, Paper, Box, TextField, IconButton } from "@mui/material"; import EditIcon from '@mui/icons-material/Edit'; import TextFieldsIcon from '@mui/icons-material/TextFields'; import DocumentScannerIcon from '@mui/icons-material/DocumentScanner'; -import { SimpleBox } from "../ui/Box"; import { WorkflowFile } from "maxun-core"; import Typography from "@mui/material/Typography"; import { useGlobalInfoStore } from "../../context/globalInfo"; @@ -12,15 +11,12 @@ import { useBrowserSteps } from '../../context/browserSteps'; import { useSocketStore } from '../../context/socket'; import { ScreenshotSettings } from '../../shared/types'; import InputAdornment from '@mui/material/InputAdornment'; -import { SidePanelHeader } from './SidePanelHeader'; import FormControlLabel from '@mui/material/FormControlLabel'; import FormControl from '@mui/material/FormControl'; import FormLabel from '@mui/material/FormLabel'; import Radio from '@mui/material/Radio'; import RadioGroup from '@mui/material/RadioGroup'; -import { emptyWorkflow } from "../../shared/constants"; import { getActiveWorkflow } from "../../api/workflow"; -import DeleteIcon from '@mui/icons-material/Delete'; import ActionDescriptionBox from '../action/ActionDescriptionBox'; import { useThemeMode } from '../../context/theme-provider'; import { useTranslation } from 'react-i18next'; From d627d4357a4d2038f7b53c177bae975b2d6d7f29 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:13:33 +0530 Subject: [PATCH 009/138] chore: remove unused import --- src/components/robot/Recordings.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/robot/Recordings.tsx b/src/components/robot/Recordings.tsx index 46484cb1..9ddfccc7 100644 --- a/src/components/robot/Recordings.tsx +++ b/src/components/robot/Recordings.tsx @@ -3,8 +3,8 @@ import { RecordingsTable } from "./RecordingsTable"; import { Grid } from "@mui/material"; import { RunSettings, RunSettingsModal } from "../run/RunSettings"; import { ScheduleSettings, ScheduleSettingsModal } from "./ScheduleSettings"; -import { IntegrationSettings, IntegrationSettingsModal } from "../integration/IntegrationSettings"; -import { RobotSettings, RobotSettingsModal } from "./RobotSettings"; +import { IntegrationSettingsModal } from "../integration/IntegrationSettings"; +import { RobotSettingsModal } from "./RobotSettings"; import { RobotEditModal } from "./RobotEdit"; import { RobotDuplicationModal } from "./RobotDuplicate"; import { useNavigate, useLocation, useParams } from "react-router-dom"; From 3c1c585dfd5ab4bcadd42ff7d8dbd3b4c87b4030 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:13:55 +0530 Subject: [PATCH 010/138] chore: remove unused import --- src/components/robot/RobotDuplicate.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/robot/RobotDuplicate.tsx b/src/components/robot/RobotDuplicate.tsx index a78e523b..efde9b2a 100644 --- a/src/components/robot/RobotDuplicate.tsx +++ b/src/components/robot/RobotDuplicate.tsx @@ -5,7 +5,6 @@ import { modalStyle } from "../recorder/AddWhereCondModal"; 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 { From 03d523857134da914063117cb3edf7d8420c8785 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:14:32 +0530 Subject: [PATCH 011/138] chore: remove unused import --- src/components/run/InterpretationButtons.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/run/InterpretationButtons.tsx b/src/components/run/InterpretationButtons.tsx index 0edcf682..a6ebb1bb 100644 --- a/src/components/run/InterpretationButtons.tsx +++ b/src/components/run/InterpretationButtons.tsx @@ -1,7 +1,6 @@ import { Box, Button, Stack, Typography, CircularProgress } from "@mui/material"; -import { PlayCircle } from "@mui/icons-material"; import React, { useCallback, useEffect, useState } from "react"; -import { interpretCurrentRecording, stopCurrentInterpretation } from "../../api/recording"; +import { interpretCurrentRecording } from "../../api/recording"; import { useSocketStore } from "../../context/socket"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { GenericModal } from "../ui/GenericModal"; From 792e56ec2d90505d7466bd24e66b766af154354a Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:17:34 +0530 Subject: [PATCH 012/138] fix: broken coordinates import in date picker --- src/components/pickers/DatePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/pickers/DatePicker.tsx b/src/components/pickers/DatePicker.tsx index 61363984..00687115 100644 --- a/src/components/pickers/DatePicker.tsx +++ b/src/components/pickers/DatePicker.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react'; import { useSocketStore } from '../../context/socket'; -import { Coordinates } from './canvas'; +import { Coordinates } from '../recorder/canvas'; interface DatePickerProps { coordinates: Coordinates; From dcc1c6364300f7428cb8e210ca2358d242d16dde Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 22:48:23 +0530 Subject: [PATCH 013/138] chore: -rm App.test.tsx --- src/App.test.tsx | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/App.test.tsx diff --git a/src/App.test.tsx b/src/App.test.tsx deleted file mode 100644 index 2a68616d..00000000 --- a/src/App.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); From 4bd161ab885ca6e2f2b45b1085a0bf139c84df76 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 22:51:31 +0530 Subject: [PATCH 014/138] feat: not found component --- src/components/dashboard/NotFound.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/components/dashboard/NotFound.tsx diff --git a/src/components/dashboard/NotFound.tsx b/src/components/dashboard/NotFound.tsx new file mode 100644 index 00000000..dc5d640d --- /dev/null +++ b/src/components/dashboard/NotFound.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +export function NotFoundPage() { + return ( +
+

404 - Page Not Found

+

Oops! This page does not. exist.

+ Go to Homepage +
+ ); + } \ No newline at end of file From b68ce4918fcfa9ff916dac8887f08b45afc670a9 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:01:56 +0530 Subject: [PATCH 015/138] feat: global route for invalid pages --- src/pages/PageWrappper.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index d778c186..f676a8a1 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -12,6 +12,7 @@ import Login from './Login'; import Register from './Register'; import UserRoute from '../routes/userRoute'; import { Routes, Route, useNavigate, Navigate } from 'react-router-dom'; +import { NotFoundPage } from '../components/dashboard/NotFound'; import { Runs } from '../components/run/Runs'; export const PageWrapper = () => { @@ -75,6 +76,7 @@ export const PageWrapper = () => { path="/register" element={} /> + } /> From f2010deb34e87f301fcfe67e067cfc6b743a404b Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:02:19 +0530 Subject: [PATCH 016/138] chore: -rm unused import --- src/pages/PageWrappper.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrappper.tsx index f676a8a1..1e73f26a 100644 --- a/src/pages/PageWrappper.tsx +++ b/src/pages/PageWrappper.tsx @@ -13,7 +13,6 @@ import Register from './Register'; import UserRoute from '../routes/userRoute'; import { Routes, Route, useNavigate, Navigate } from 'react-router-dom'; import { NotFoundPage } from '../components/dashboard/NotFound'; -import { Runs } from '../components/run/Runs'; export const PageWrapper = () => { const [open, setOpen] = useState(false); From 5272b1c06fc8896ec82163a8be45a93613f6203d Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:02:35 +0530 Subject: [PATCH 017/138] chore: lint --- src/components/dashboard/NotFound.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/dashboard/NotFound.tsx b/src/components/dashboard/NotFound.tsx index dc5d640d..4bf01d91 100644 --- a/src/components/dashboard/NotFound.tsx +++ b/src/components/dashboard/NotFound.tsx @@ -1,11 +1,11 @@ import React from 'react'; export function NotFoundPage() { - return ( -
-

404 - Page Not Found

-

Oops! This page does not. exist.

- Go to Homepage -
- ); - } \ No newline at end of file + return ( +
+

404 - Page Not Found

+

Oops! This page does not. exist.

+ Go to Homepage +
+ ); +} \ No newline at end of file From 0b8d4868b5256461d26986f699c4216c2256ebcd Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:04:35 +0530 Subject: [PATCH 018/138] fix: not found message --- src/components/dashboard/NotFound.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/dashboard/NotFound.tsx b/src/components/dashboard/NotFound.tsx index 4bf01d91..0b24986d 100644 --- a/src/components/dashboard/NotFound.tsx +++ b/src/components/dashboard/NotFound.tsx @@ -4,8 +4,8 @@ export function NotFoundPage() { return (

404 - Page Not Found

-

Oops! This page does not. exist.

- Go to Homepage +

Oops! This page does not exist.

+ Take me to the homepage
); } \ No newline at end of file From e643718404526e77d15bccce6fec7da58f5d6f5c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:05:04 +0530 Subject: [PATCH 019/138] feat: set text decoration to none --- src/components/dashboard/NotFound.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/dashboard/NotFound.tsx b/src/components/dashboard/NotFound.tsx index 0b24986d..456c6f1d 100644 --- a/src/components/dashboard/NotFound.tsx +++ b/src/components/dashboard/NotFound.tsx @@ -5,7 +5,7 @@ export function NotFoundPage() {

404 - Page Not Found

Oops! This page does not exist.

- Take me to the homepage + Take me to the homepage
); } \ No newline at end of file From ec0867eb6e6f0fc669a6486b1d2b7abad2f30456 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:05:58 +0530 Subject: [PATCH 020/138] fix: -rm unused style --- src/components/dashboard/NotFound.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/dashboard/NotFound.tsx b/src/components/dashboard/NotFound.tsx index 456c6f1d..ab9d4717 100644 --- a/src/components/dashboard/NotFound.tsx +++ b/src/components/dashboard/NotFound.tsx @@ -2,7 +2,7 @@ import React from 'react'; export function NotFoundPage() { return ( -
+

404 - Page Not Found

Oops! This page does not exist.

Take me to the homepage From a324220275400c6567996af51fd2361608824dff Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 23:07:07 +0530 Subject: [PATCH 021/138] fix: format --- src/components/dashboard/NotFound.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/dashboard/NotFound.tsx b/src/components/dashboard/NotFound.tsx index ab9d4717..9b81acb0 100644 --- a/src/components/dashboard/NotFound.tsx +++ b/src/components/dashboard/NotFound.tsx @@ -5,7 +5,7 @@ export function NotFoundPage() {

404 - Page Not Found

Oops! This page does not exist.

- Take me to the homepage + Take me to the homepage
); } \ No newline at end of file From 0f5dec179c0fcc4738ccf51c762f6b09bbe67b88 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 16 Jan 2025 22:49:22 +0530 Subject: [PATCH 022/138] fix: rename to PageWrapper.tsx --- src/pages/{PageWrappper.tsx => PageWrapper.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/pages/{PageWrappper.tsx => PageWrapper.tsx} (100%) diff --git a/src/pages/PageWrappper.tsx b/src/pages/PageWrapper.tsx similarity index 100% rename from src/pages/PageWrappper.tsx rename to src/pages/PageWrapper.tsx From fd3538694218bbbe0bd04f3fcb879f9e3dd053eb Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 16 Jan 2025 22:49:51 +0530 Subject: [PATCH 023/138] fix: broken page wrapper import --- src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index cdee8d40..b8497f58 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,7 +2,7 @@ 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 { PageWrapper } from "./pages/PageWrapper"; import i18n from "./i18n"; import ThemeModeProvider from './context/theme-provider'; From b756af0ea1e0551106bb99488140974d102ae648 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 17 Jan 2025 22:46:37 +0530 Subject: [PATCH 024/138] chore: cleanup --- src/components/run/RunsTable.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index b652aef0..73167b52 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -18,7 +18,6 @@ import { getStoredRuns } from "../../api/storage"; import { RunSettings } from "./RunSettings"; import { CollapsibleRow } from "./ColapsibleRow"; -// Export columns before the component export const columns: readonly Column[] = [ { id: 'runStatus', label: 'Status', minWidth: 80 }, { id: 'name', label: 'Name', minWidth: 80 }, @@ -70,7 +69,6 @@ export const RunsTable: React.FC = ({ const { t } = useTranslation(); const navigate = useNavigate(); - // Update column labels using translation if needed const translatedColumns = columns.map(column => ({ ...column, label: t(`runstable.${column.id}`, column.label) From 88ed7717dceb0b70ddd62c90f84a444f9ba3a8a2 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 17 Jan 2025 22:50:44 +0530 Subject: [PATCH 025/138] feat: show circular progress while runs load --- src/components/run/RunsTable.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index 73167b52..6b3b7140 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -160,6 +160,11 @@ export const RunsTable: React.FC = ({ sx={{ width: '250px' }} /> + {rows.length === 0 ? ( + + + + ) : ( {Object.entries(groupedRows).map(([id, data]) => ( handleAccordionChange(id, isExpanded)}> @@ -202,6 +207,7 @@ export const RunsTable: React.FC = ({ ))} + )} Date: Fri, 17 Jan 2025 22:51:01 +0530 Subject: [PATCH 026/138] fix: circular progress import --- src/components/run/RunsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index 6b3b7140..676669fd 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -9,7 +9,7 @@ import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TablePagination from '@mui/material/TablePagination'; import TableRow from '@mui/material/TableRow'; -import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField } from '@mui/material'; +import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField, CircularProgress } from '@mui/material'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import SearchIcon from '@mui/icons-material/Search'; import { useNavigate } from 'react-router-dom'; From 28a0c8f8821ce7f5e3d6382cb5a7dfb97b8f5b67 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 17 Jan 2025 22:51:12 +0530 Subject: [PATCH 027/138] chore: lint --- src/components/run/RunsTable.tsx | 84 ++++++++++++++++---------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index 676669fd..e6d88f48 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -165,48 +165,48 @@ export const RunsTable: React.FC = ({ ) : ( - - {Object.entries(groupedRows).map(([id, data]) => ( - handleAccordionChange(id, isExpanded)}> - }> - {data[data.length - 1].name} - - - - - - - {translatedColumns.map((column) => ( - - {column.label} - - ))} - - - - {data - .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) - .map((row) => ( - - ))} - -
-
-
- ))} -
+ + {Object.entries(groupedRows).map(([id, data]) => ( + handleAccordionChange(id, isExpanded)}> + }> + {data[data.length - 1].name} + + + + + + + {translatedColumns.map((column) => ( + + {column.label} + + ))} + + + + {data + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((row) => ( + + ))} + +
+
+
+ ))} +
)} Date: Fri, 17 Jan 2025 22:52:30 +0530 Subject: [PATCH 028/138] feat: set height to 50% --- src/components/run/RunsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index e6d88f48..1264dd3c 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -161,7 +161,7 @@ export const RunsTable: React.FC = ({ /> {rows.length === 0 ? ( - + ) : ( From 7fd29d23e0179825756e1a7e3be91d34b8ae502c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 17 Jan 2025 22:54:05 +0530 Subject: [PATCH 029/138] feat: show circular progress while robots load --- src/components/robot/RecordingsTable.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 4bbcb654..718400db 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -200,6 +200,11 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl + {rows.length === 0 ? ( + + + + ) : ( @@ -295,6 +300,7 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl
+ )} Date: Fri, 17 Jan 2025 22:54:17 +0530 Subject: [PATCH 030/138] fix: circular progress import --- src/components/robot/RecordingsTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 718400db..14c51628 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -11,7 +11,7 @@ import TableRow from '@mui/material/TableRow'; import { useEffect } from "react"; import { WorkflowFile } from "maxun-core"; import SearchIcon from '@mui/icons-material/Search'; -import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText } from "@mui/material"; +import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText, CircularProgress } from "@mui/material"; import { Schedule, DeleteForever, Edit, PlayCircle, Settings, Power, ContentCopy, MoreHoriz } from "@mui/icons-material"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { checkRunsForRecording, deleteRecordingFromStorage, getStoredRecordings } from "../../api/storage"; From 395a352331693f3bd0d213febcb691f119fd15b3 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Fri, 17 Jan 2025 22:54:34 +0530 Subject: [PATCH 031/138] chore: lint --- src/components/robot/RecordingsTable.tsx | 196 +++++++++++------------ 1 file changed, 98 insertions(+), 98 deletions(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 14c51628..87327b7e 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -200,107 +200,107 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl - {rows.length === 0 ? ( - - - - ) : ( - - - - - {columns.map((column) => ( - - {column.label} - - ))} - - - - {filteredRows.length !== 0 ? filteredRows - .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) - .map((row) => { - return ( - - {columns.map((column) => { - // @ts-ignore - const value: any = row[column.id]; - if (value !== undefined) { - return ( - - {value} - - ); - } else { - switch (column.id) { - case 'interpret': - return ( - - handleRunRecording(row.id, row.name, row.params || [])} /> - - ); - case 'schedule': - return ( - - handleScheduleRecording(row.id, row.name, row.params || [])} /> - - ); - case 'integrate': - return ( - - handleIntegrateRecording(row.id, row.name, row.params || [])} /> - - ); - case 'options': - return ( - - handleEditRobot(row.id, row.name, row.params || [])} - handleDuplicate={() => { - handleDuplicateRobot(row.id, row.name, row.params || []); - }} - handleDelete={() => { + {rows.length === 0 ? ( + + + + ) : ( + +
+ + + {columns.map((column) => ( + + {column.label} + + ))} + + + + {filteredRows.length !== 0 ? filteredRows + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((row) => { + return ( + + {columns.map((column) => { + // @ts-ignore + const value: any = row[column.id]; + if (value !== undefined) { + return ( + + {value} + + ); + } else { + switch (column.id) { + case 'interpret': + return ( + + handleRunRecording(row.id, row.name, row.params || [])} /> + + ); + case 'schedule': + return ( + + handleScheduleRecording(row.id, row.name, row.params || [])} /> + + ); + case 'integrate': + return ( + + handleIntegrateRecording(row.id, row.name, row.params || [])} /> + + ); + case 'options': + return ( + + handleEditRobot(row.id, row.name, row.params || [])} + handleDuplicate={() => { + handleDuplicateRobot(row.id, row.name, row.params || []); + }} + handleDelete={() => { - checkRunsForRecording(row.id).then((result: boolean) => { - if (result) { - notify('warning', t('recordingtable.notifications.delete_warning')); - } - }) + checkRunsForRecording(row.id).then((result: boolean) => { + if (result) { + notify('warning', t('recordingtable.notifications.delete_warning')); + } + }) - deleteRecordingFromStorage(row.id).then((result: boolean) => { - if (result) { - setRows([]); - notify('success', t('recordingtable.notifications.delete_success')); - fetchRecordings(); - } - }) - }} - /> - - ); - case 'settings': - return ( - - handleSettingsRecording(row.id, row.name, row.params || [])} /> - - ); - default: - return null; + deleteRecordingFromStorage(row.id).then((result: boolean) => { + if (result) { + setRows([]); + notify('success', t('recordingtable.notifications.delete_success')); + fetchRecordings(); + } + }) + }} + /> + + ); + case 'settings': + return ( + + handleSettingsRecording(row.id, row.name, row.params || [])} /> + + ); + default: + return null; + } } - } - })} - - ); - }) - : null} - -
-
- )} + })} + + ); + }) + : null} + + + + )} Date: Sat, 18 Jan 2025 20:32:59 +0530 Subject: [PATCH 032/138] fix: use maxun.dev --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 376bf25b..13c994a0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

- +
Maxun From a2ec9a6b678f8407b7773d9303ba5ee770fd1513 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 18 Jan 2025 20:49:47 +0530 Subject: [PATCH 033/138] feat: use light mode icon --- src/components/dashboard/NavBar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/dashboard/NavBar.tsx b/src/components/dashboard/NavBar.tsx index 663f6900..cbe68f05 100644 --- a/src/components/dashboard/NavBar.tsx +++ b/src/components/dashboard/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, Tooltip } from "@mui/material"; -import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Brightness7, Brightness4, Description } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Brightness7, Brightness4, Description, LightMode } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../recorder/SaveRecording'; @@ -114,7 +114,7 @@ export const NavBar: React.FC = ({ } }} > - {darkMode ? : } + {darkMode ? : } ); From d2e2dd0010caa4b0850cac558eae931995909120 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 18 Jan 2025 20:51:22 +0530 Subject: [PATCH 034/138] feat: use dark mode icon --- src/components/dashboard/NavBar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/dashboard/NavBar.tsx b/src/components/dashboard/NavBar.tsx index cbe68f05..b624b4b8 100644 --- a/src/components/dashboard/NavBar.tsx +++ b/src/components/dashboard/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, Tooltip } from "@mui/material"; -import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Brightness7, Brightness4, Description, LightMode } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Brightness7, Brightness4, Description, LightMode, DarkMode } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../recorder/SaveRecording'; @@ -114,7 +114,7 @@ export const NavBar: React.FC = ({ } }} > - {darkMode ? : } + {darkMode ? : } ); From 54b7dc8154e5a98926a3fc833e171ade5af8e13e Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 18 Jan 2025 20:53:43 +0530 Subject: [PATCH 035/138] fix: remove unused imports --- src/components/dashboard/NavBar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/dashboard/NavBar.tsx b/src/components/dashboard/NavBar.tsx index b624b4b8..31eed9f1 100644 --- a/src/components/dashboard/NavBar.tsx +++ b/src/components/dashboard/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, Tooltip } from "@mui/material"; -import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Brightness7, Brightness4, Description, LightMode, DarkMode } from "@mui/icons-material"; +import { AccountCircle, Logout, Clear, YouTube, X, Update, Close, Language, Description, LightMode, DarkMode } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../recorder/SaveRecording'; From a62f87eefec7cabfea374f6040d7a07d41ccf0bf Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 19 Jan 2025 23:07:16 +0530 Subject: [PATCH 036/138] chore: remove dbus config --- server/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index becad25c..9788182c 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -44,9 +44,6 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /tmp/.X11-unix && chmod 1777 /tmp/.X11-unix -# Add a dbus configuration to prevent connection errors -# RUN mkdir -p /var/run/dbus - # Make the script executable # RUN chmod +x ./start.sh From dd51202bd2efaeeddcbef08bae3da2e1adc88a13 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 19 Jan 2025 23:07:39 +0530 Subject: [PATCH 037/138] chore: remove executable script --- server/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index 9788182c..e7d1a061 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -44,9 +44,6 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* \ && mkdir -p /tmp/.X11-unix && chmod 1777 /tmp/.X11-unix -# Make the script executable -# RUN chmod +x ./start.sh - # Expose the backend port EXPOSE ${BACKEND_PORT:-8080} From dfcb3f1702d02d9851f4625a0490c95fd5a5018f Mon Sep 17 00:00:00 2001 From: Rohit Date: Mon, 20 Jan 2025 16:35:53 +0530 Subject: [PATCH 038/138] feat: add login needed ui for recording --- src/components/robot/RecordingsTable.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 87327b7e..e7409b89 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -11,7 +11,7 @@ import TableRow from '@mui/material/TableRow'; import { useEffect } from "react"; import { WorkflowFile } from "maxun-core"; import SearchIcon from '@mui/icons-material/Search'; -import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText, CircularProgress } from "@mui/material"; +import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText, CircularProgress, RadioGroup, FormControlLabel, Radio } from "@mui/material"; import { Schedule, DeleteForever, Edit, PlayCircle, Settings, Power, ContentCopy, MoreHoriz } from "@mui/icons-material"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { checkRunsForRecording, deleteRecordingFromStorage, getStoredRecordings } from "../../api/storage"; @@ -85,7 +85,7 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl }, ]; - const { notify, setRecordings, browserId, setBrowserId, setInitialUrl, recordingUrl, setRecordingUrl, recordingName, setRecordingName, recordingId, setRecordingId } = useGlobalInfoStore(); + const { notify, setRecordings, browserId, setBrowserId, setInitialUrl, recordingUrl, setRecordingUrl, isLogin, setIsLogin, recordingName, setRecordingName, recordingId, setRecordingId } = useGlobalInfoStore(); const navigate = useNavigate(); const handleChangePage = (event: unknown, newPage: number) => { @@ -321,6 +321,19 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl onChange={setBrowserRecordingUrl} style={{ marginBottom: '20px', marginTop: '20px' }} /> + + {t('recordingtable.modal.login_title')} + setIsLogin(e.target.value === 'yes')} + style={{ marginBottom: '20px' }} + > + } label="Yes" /> + } label="No" /> + + - - - - ) - } + + + + + + )} ); -}; +}; \ No newline at end of file From ef3ec295d7ee24eebd49be8a496d9b7193598818 Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 01:17:38 +0530 Subject: [PATCH 084/138] feat: add types for credentials --- src/api/storage.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/api/storage.ts b/src/api/storage.ts index c7901f22..290f6e7f 100644 --- a/src/api/storage.ts +++ b/src/api/storage.ts @@ -5,8 +5,13 @@ import { ScheduleSettings } from "../components/robot/ScheduleSettings"; import { CreateRunResponse, ScheduleRunResponse } from "../pages/MainPage"; import { apiUrl } from "../apiConfig"; +interface CredentialInfo { + value: string; + type: string; +} + interface Credentials { - [key: string]: string; + [key: string]: CredentialInfo; } export const getStoredRecordings = async (): Promise => { From ee65ea84061f19e48929f69962a70d75077e5ba9 Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 01:18:47 +0530 Subject: [PATCH 085/138] feat: add input type for workflow type actions --- server/src/routes/storage.ts | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 007ac40c..fb587d17 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -154,48 +154,52 @@ function formatRunResponse(run: any) { return formattedRun; } -interface CredentialUpdate { - [selector: string]: string; +interface CredentialInfo { + value: string; + type: string; } -function updateTypeActionsInWorkflow(workflow: any[], credentials: CredentialUpdate) { +interface Credentials { + [key: string]: CredentialInfo; +} + +function updateTypeActionsInWorkflow(workflow: any[], credentials: Credentials) { return workflow.map(step => { if (!step.what) return step; - // First pass: mark indices to remove const indicesToRemove = new Set(); - step.what.forEach((action: any, index: any) => { + step.what.forEach((action: any, index: number) => { if (!action.action || !action.args?.[0]) return; - // If it's a type/press action for a credential if ((action.action === 'type' || action.action === 'press') && credentials[action.args[0]]) { indicesToRemove.add(index); - // Check if next action is waitForLoadState + if (step.what[index + 1]?.action === 'waitForLoadState') { indicesToRemove.add(index + 1); } } }); - // Filter out marked indices and create new what array - const filteredWhat = step.what.filter((_: any, index: any) => !indicesToRemove.has(index)); + const filteredWhat = step.what.filter((_: any, index: number) => !indicesToRemove.has(index)); - // Add new type actions after click actions - Object.entries(credentials).forEach(([selector, credential]) => { + Object.entries(credentials).forEach(([selector, credentialInfo]) => { const clickIndex = filteredWhat.findIndex((action: any) => action.action === 'click' && action.args?.[0] === selector ); if (clickIndex !== -1) { - const chars = credential.split(''); + const chars = credentialInfo.value.split(''); + chars.forEach((char, i) => { - // Add type action filteredWhat.splice(clickIndex + 1 + (i * 2), 0, { action: 'type', - args: [selector, encrypt(char)] + args: [ + selector, + encrypt(char), + credentialInfo.type + ] }); - // Add waitForLoadState filteredWhat.splice(clickIndex + 2 + (i * 2), 0, { action: 'waitForLoadState', args: ['networkidle'] From 1950cc582b4df49b550e4e128196657f8608576c Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 01:53:04 +0530 Subject: [PATCH 086/138] feat: rm letter on backspace --- src/components/robot/RobotEdit.tsx | 62 +++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index c4e75286..8d611a68 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -135,38 +135,72 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const extractInitialCredentials = (workflow: any[]): Credentials => { const credentials: Credentials = {}; - + + // Helper function to check if a character is printable const isPrintableCharacter = (char: string): boolean => { return char.length === 1 && !!char.match(/^[\x20-\x7E]$/); }; - + + // Process each step in the workflow workflow.forEach(step => { if (!step.what) return; - + + // Keep track of the current input field being processed + let currentSelector = ''; + let currentValue = ''; + let currentType = ''; + + // Process actions in sequence to maintain correct text state step.what.forEach((action: any) => { if ( (action.action === 'type' || action.action === 'press') && action.args?.length >= 2 && typeof action.args[1] === 'string' ) { - const currentSelector: string = action.args[0]; + const selector: string = action.args[0]; const character: string = action.args[1]; const inputType: string = action.args[2] || ''; - - if (!credentials.hasOwnProperty(currentSelector)) { - credentials[currentSelector] = { - value: '', - type: inputType - }; + + // If we're dealing with a new selector, store the previous one + if (currentSelector && selector !== currentSelector) { + if (!credentials[currentSelector]) { + credentials[currentSelector] = { + value: currentValue, + type: currentType + }; + } else { + credentials[currentSelector].value = currentValue; + } } - - if (isPrintableCharacter(character)) { - credentials[currentSelector].value += character; + + // Update current tracking variables + if (selector !== currentSelector) { + currentSelector = selector; + currentValue = credentials[selector]?.value || ''; + currentType = inputType || credentials[selector]?.type || ''; } + + // Handle different types of key actions + if (character === 'Backspace') { + // Remove the last character when backspace is pressed + currentValue = currentValue.slice(0, -1); + } else if (isPrintableCharacter(character)) { + // Add the character to the current value + currentValue += character; + } + // Note: We ignore other special keys like 'Shift', 'Enter', etc. } }); + + // Store the final state of the last processed selector + if (currentSelector) { + credentials[currentSelector] = { + value: currentValue, + type: currentType + }; + } }); - + return credentials; }; From d56623f97a5ef7207d49a661c23888268ef8189d Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 15:45:44 +0530 Subject: [PATCH 087/138] feat: add position of text for input click event --- .../workflow-management/classes/Generator.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 47e6f377..528532d8 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -354,6 +354,40 @@ export class WorkflowGenerator { const elementInfo = await getElementInformation(page, coordinates, '', false); console.log("Element info: ", elementInfo); + if ((elementInfo?.tagName === 'INPUT' || elementInfo?.tagName === 'TEXTAREA') && selector) { + // Calculate the exact position within the element + const elementPos = await page.evaluate((selector) => { + const element = document.querySelector(selector); + if (!element) return null; + const rect = element.getBoundingClientRect(); + return { + x: rect.left, + y: rect.top + }; + }, selector); + + if (elementPos) { + const relativeX = coordinates.x - elementPos.x; + const relativeY = coordinates.y - elementPos.y; + + const pair: WhereWhatPair = { + where, + what: [{ + action: 'click', + args: [selector, { position: { x: relativeX, y: relativeY } }] + }] + }; + + if (selector) { + this.generatedData.lastUsedSelector = selector; + this.generatedData.lastAction = 'click'; + } + + await this.addPairToWorkflowAndNotifyClient(pair, page); + return; + } + } + // Check if clicked element is a select dropdown const isDropdown = elementInfo?.tagName === 'SELECT'; From 2abf0f0d7bdd3991168b7c73663b9a338d61e889 Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 20:23:53 +0530 Subject: [PATCH 088/138] feat: check visibility --- src/components/robot/RobotEdit.tsx | 55 +++++++++++++++++------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 8d611a68..e96fc858 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -320,30 +320,37 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {headerText} - {selectors.map((selector) => ( - handleCredentialChange(selector, e.target.value)} - style={{ marginBottom: '20px' }} - InputProps={{ - // Only show visibility toggle for password fields - endAdornment: defaultType === 'password' ? ( - - handleClickShowPassword(selector)} - edge="end" - > - {showPasswords[selector] ? : } - - - ) : undefined, - }} - /> - ))} + {selectors.map((selector) => { + const isVisible = showPasswords[selector]; + + return ( + handleCredentialChange(selector, e.target.value)} + style={{ marginBottom: '20px' }} + InputProps={{ + // Now showing visibility toggle for all fields + endAdornment: ( + + handleClickShowPassword(selector)} + edge="end" + // Optional: disable if field is empty + disabled={!credentials[selector]?.value} + > + {isVisible ? : } + + + ), + }} + /> + ); + })} ); }; From 58ed90b2e61c59b2f51f146a45a439d8eefa61fc Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 23 Jan 2025 20:49:30 +0530 Subject: [PATCH 089/138] fix: format --- src/components/robot/RecordingsTable.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 6297c7aa..a36707e7 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -76,7 +76,14 @@ interface RecordingsTableProps { handleDuplicateRobot: (id: string, name: string, params: string[]) => void; } -export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording, handleEditRobot, handleDuplicateRobot }: 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); From e0f58bb3d098d72a106ddc286d18ec0106aafb3c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 23 Jan 2025 20:50:16 +0530 Subject: [PATCH 090/138] fix: format --- src/components/robot/RecordingsTable.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index a36707e7..a7594b08 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -116,7 +116,20 @@ export const RecordingsTable = ({ }, ]; - const { notify, setRecordings, browserId, setBrowserId, setInitialUrl, recordingUrl, setRecordingUrl, isLogin, setIsLogin, recordingName, setRecordingName, recordingId, setRecordingId } = useGlobalInfoStore(); + const { + notify, + setRecordings, + browserId, + setBrowserId, + setInitialUrl, + recordingUrl, + setRecordingUrl, + isLogin, + setIsLogin, + recordingName, + setRecordingName, + recordingId, + setRecordingId } = useGlobalInfoStore(); const navigate = useNavigate(); const handleChangePage = (event: unknown, newPage: number) => { From 76a785b4604f0dec980ad26b7d66dd70b1e03b23 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 23 Jan 2025 20:54:23 +0530 Subject: [PATCH 091/138] chore: cleanup --- src/components/robot/RobotEdit.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index e96fc858..f8e85a77 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -8,7 +8,6 @@ import { useGlobalInfoStore } from '../../context/globalInfo'; import { getStoredRecording, updateRecording } from '../../api/storage'; import { WhereWhatPair } from 'maxun-core'; -// Base interfaces for robot data structure interface RobotMeta { name: string; id: string; From 011a6edf05ff23f379a751349746b6e1f407c5b1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 23 Jan 2025 20:54:34 +0530 Subject: [PATCH 092/138] chore: cleanup --- src/components/robot/RobotEdit.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index f8e85a77..c9b7bbd6 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -54,7 +54,6 @@ interface RobotSettingsProps { initialSettings?: RobotSettings | null; } -// Enhanced interfaces for credential handling interface CredentialInfo { value: string; type: string; From 3cc23f9854b235aace43d3e65161d6de6dfeb844 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Thu, 23 Jan 2025 20:55:10 +0530 Subject: [PATCH 093/138] chore: cleanup --- src/components/robot/RobotEdit.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index c9b7bbd6..035165ba 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -113,7 +113,6 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return 'username'; } - // If no specific pattern is matched, classify as other return 'other'; }; From 357488c801b442eb8c38d3cfcf18210d1cd602d4 Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 24 Jan 2025 12:15:24 +0530 Subject: [PATCH 094/138] feat: add check to see if robot is running --- .../browser-management/classes/BrowserPool.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/server/src/browser-management/classes/BrowserPool.ts b/server/src/browser-management/classes/BrowserPool.ts index cd4962a1..ecd3c9dc 100644 --- a/server/src/browser-management/classes/BrowserPool.ts +++ b/server/src/browser-management/classes/BrowserPool.ts @@ -15,6 +15,8 @@ interface BrowserPoolInfo { * @default false */ active: boolean, + + isRobotRun?: boolean; } /** @@ -46,17 +48,29 @@ export class BrowserPool { * @param browser remote browser instance * @param active states if the browser's instance is being actively used */ - public addRemoteBrowser = (id: string, browser: RemoteBrowser, active: boolean = false): void => { + public addRemoteBrowser = (id: string, browser: RemoteBrowser, active: boolean = false, isRobotRun: boolean = false): void => { this.pool = { ...this.pool, [id]: { browser, active, + isRobotRun }, } logger.log('debug', `Remote browser with id: ${id} added to the pool`); }; + public hasActiveRobotRun(): boolean { + return Object.values(this.pool).some(info => info.isRobotRun); + } + + public clearRobotRunState(id: string): void { + if (this.pool[id]) { + this.pool[id].isRobotRun = false; + logger.log('debug', `Robot run state cleared for browser ${id}`); + } + } + /** * Removes the remote browser instance from the pool. * @param id remote browser instance's id @@ -67,6 +81,8 @@ export class BrowserPool { logger.log('warn', `Remote browser with id: ${id} does not exist in the pool`); return false; } + + this.clearRobotRunState(id); delete (this.pool[id]); logger.log('debug', `Remote browser with id: ${id} deleted from the pool`); return true; From 1ec5b3bf7d3f4bbd5b3adb21a08ded50b50c4c81 Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 24 Jan 2025 12:16:44 +0530 Subject: [PATCH 095/138] feat: add route to verify is robot is running --- server/src/routes/record.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/server/src/routes/record.ts b/server/src/routes/record.ts index 51d3ff92..17146173 100644 --- a/server/src/routes/record.ts +++ b/server/src/routes/record.ts @@ -16,6 +16,7 @@ import stealthPlugin from 'puppeteer-extra-plugin-stealth'; import logger from "../logger"; import { getDecryptedProxyConfig } from './proxy'; import { requireSignIn } from '../middlewares/auth'; +import { browserPool } from '../server'; export const router = Router(); chromium.use(stealthPlugin()); @@ -33,6 +34,17 @@ router.all('/', requireSignIn, (req, res, next) => { next() // pass control to the next handler }) +router.use('/', requireSignIn, (req: AuthenticatedRequest, res: Response, next) => { + if (browserPool.hasActiveRobotRun()) { + logger.log('debug', 'Preventing browser initialization - robot run in progress'); + return res.status(403).json({ + error: 'Cannot initialize recording browser while a robot run is in progress' + }); + } + next(); +}); + + /** * GET endpoint for starting the remote browser recording session. * returns session's id From 067627bf396829c29abe2305f0461b4cb6906ccd Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 24 Jan 2025 13:47:17 +0530 Subject: [PATCH 096/138] feat: notify on robot run after page reload --- src/pages/MainPage.tsx | 77 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 7 deletions(-) diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index b9a4f24f..c8066951 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -68,13 +68,14 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) const readyForRunHandler = useCallback((browserId: string, runId: string) => { interpretStoredRecording(runId).then(async (interpretation: boolean) => { if (!aborted) { - if (interpretation) { - notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); - } else { - notify('success', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); - // destroy the created browser - await stopRecording(browserId); - } + // if (interpretation) { + // notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); + // } else { + // notify('success', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); + // // destroy the created browser + // await stopRecording(browserId); + // } + if (!interpretation) await stopRecording(browserId); } setRunningRecordingName(''); setCurrentInterpretationLog(''); @@ -89,6 +90,12 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) const handleRunRecording = useCallback((settings: RunSettings) => { createRunForStoredRecording(runningRecordingId, settings).then(({ browserId, runId }: CreateRunResponse) => { + localStorage.setItem('runInfo', JSON.stringify({ + browserId, + runId, + recordingName: runningRecordingName + })); + setIds({ browserId, runId }); const socket = io(`${apiUrl}/${browserId}`, { @@ -98,6 +105,18 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) setSockets(sockets => [...sockets, socket]); socket.on('ready-for-run', () => readyForRunHandler(browserId, runId)); socket.on('debugMessage', debugMessageHandler); + + socket.on('run-completed', (status) => { + if (status === 'success') { + notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); + } else { + notify('error', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); + } + setRunningRecordingName(''); + setCurrentInterpretationLog(''); + setRerenderRuns(true); + }); + setContent('runs'); if (browserId) { notify('info', t('main_page.notifications.run_started', { name: runningRecordingName })); @@ -108,6 +127,7 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) return (socket: Socket, browserId: string, runId: string) => { socket.off('ready-for-run', () => readyForRunHandler(browserId, runId)); socket.off('debugMessage', debugMessageHandler); + socket.off('run-completed'); } }, [runningRecordingName, sockets, ids, readyForRunHandler, debugMessageHandler]) @@ -122,6 +142,49 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) }); } + useEffect(() => { + const storedRunInfo = localStorage.getItem('runInfo'); + console.log('storedRunInfo', storedRunInfo); + + if (storedRunInfo) { + // Parse the stored info + const { browserId, runId, recordingName } = JSON.parse(storedRunInfo); + + // Reconnect to the specific browser's namespace + setIds({ browserId, runId }); + const socket = io(`${apiUrl}/${browserId}`, { + transports: ["websocket"], + rejectUnauthorized: false + }); + + // Update component state with stored info + setRunningRecordingName(recordingName); + setSockets(sockets => [...sockets, socket]); + + // Set up event listeners + socket.on('ready-for-run', () => readyForRunHandler(browserId, runId)); + socket.on('debugMessage', debugMessageHandler); + socket.on('run-completed', (status) => { + if (status === 'success') { + notify('success', t('main_page.notifications.interpretation_success', { name: recordingName })); + } else { + notify('error', t('main_page.notifications.interpretation_failed', { name: recordingName })); + } + setRunningRecordingName(''); + setCurrentInterpretationLog(''); + setRerenderRuns(true); + localStorage.removeItem('runInfo'); // Clean up stored info + }); + + // Cleanup function + return () => { + socket.off('ready-for-run', () => readyForRunHandler(browserId, runId)); + socket.off('debugMessage', debugMessageHandler); + socket.off('run-completed'); + }; + } + }, []); + const DisplayContent = () => { switch (content) { case 'robots': From 8619435f2dfb38e1622f10efd1e50543071ba33b Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 24 Jan 2025 13:48:49 +0530 Subject: [PATCH 097/138] feat: update state as true on run creation --- server/src/browser-management/controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/browser-management/controller.ts b/server/src/browser-management/controller.ts index 24a677ce..f589ce3f 100644 --- a/server/src/browser-management/controller.ts +++ b/server/src/browser-management/controller.ts @@ -59,7 +59,7 @@ export const createRemoteBrowserForRun = (userId: string): string => { async (socket: Socket) => { const browserSession = new RemoteBrowser(socket); await browserSession.initialize(userId); - browserPool.addRemoteBrowser(id, browserSession, true); + browserPool.addRemoteBrowser(id, browserSession, true, true); socket.emit('ready-for-run'); }); return id; From 102c72afa239f2e998db3741caf78d94ee658cbb Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 24 Jan 2025 13:49:31 +0530 Subject: [PATCH 098/138] feat: emit run completed socket event --- server/src/workflow-management/classes/Interpreter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/workflow-management/classes/Interpreter.ts b/server/src/workflow-management/classes/Interpreter.ts index c8aec13c..661f58db 100644 --- a/server/src/workflow-management/classes/Interpreter.ts +++ b/server/src/workflow-management/classes/Interpreter.ts @@ -332,6 +332,8 @@ export class WorkflowInterpreter { }, {}) } + this.socket.emit('run-completed', "success"); + logger.log('debug', `Interpretation finished`); this.clearState(); return result; From afc1155354565568a3a1b5ccf873341710fff63a Mon Sep 17 00:00:00 2001 From: Rohit Date: Fri, 24 Jan 2025 14:08:36 +0530 Subject: [PATCH 099/138] feat: add translation for label field --- 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, 10 insertions(+), 5 deletions(-) diff --git a/public/locales/de.json b/public/locales/de.json index 21b71313..d14f36f6 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -205,7 +205,8 @@ "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" + "capture_list_discarded": "Listenerfassung verworfen", + "label_required": "Beschriftung darf nicht leer sein" } }, "save_recording": { diff --git a/public/locales/en.json b/public/locales/en.json index a51f6c65..64ac4177 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -207,7 +207,8 @@ "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" + "capture_list_discarded": "Capture List Discarded", + "label_required": "Label cannot be empty" } }, "save_recording": { diff --git a/public/locales/es.json b/public/locales/es.json index 8ef9b8bf..c0a39216 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -206,7 +206,8 @@ "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" + "capture_list_discarded": "Captura de lista descartada", + "label_required": "La etiqueta no puede estar vacía" } }, "save_recording": { diff --git a/public/locales/ja.json b/public/locales/ja.json index 03f91cf6..676b2149 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -206,7 +206,8 @@ "confirm_text_fields": "すべてのテキストフィールドを確認してください", "unable_create_settings": "リスト設定を作成できません。リストのフィールドを定義したことを確認してください。", "capture_text_discarded": "テキスト取得が破棄されました", - "capture_list_discarded": "リスト取得が破棄されました" + "capture_list_discarded": "リスト取得が破棄されました", + "label_required": "ラベルは空にできません" } }, "save_recording": { diff --git a/public/locales/zh.json b/public/locales/zh.json index 41e3a762..d7f7a9d2 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -206,7 +206,8 @@ "confirm_text_fields": "请确认所有文本字段", "unable_create_settings": "无法创建列表设置。请确保您已为列表定义了字段。", "capture_text_discarded": "文本捕获已放弃", - "capture_list_discarded": "列表捕获已放弃" + "capture_list_discarded": "列表捕获已放弃", + "label_required": "标签不能为空" } }, "save_recording": { From 153cf81edc4d113c83135b895168e7202b67123b Mon Sep 17 00:00:00 2001 From: Karishma Shukla Date: Fri, 24 Jan 2025 19:28:04 +0530 Subject: [PATCH 100/138] Revert "fix: prevent page reload on run trigger to open remote browser" --- .../browser-management/classes/BrowserPool.ts | 18 +---- server/src/browser-management/controller.ts | 2 +- server/src/routes/record.ts | 12 --- .../classes/Interpreter.ts | 2 - src/pages/MainPage.tsx | 77 ++----------------- 5 files changed, 9 insertions(+), 102 deletions(-) diff --git a/server/src/browser-management/classes/BrowserPool.ts b/server/src/browser-management/classes/BrowserPool.ts index ecd3c9dc..cd4962a1 100644 --- a/server/src/browser-management/classes/BrowserPool.ts +++ b/server/src/browser-management/classes/BrowserPool.ts @@ -15,8 +15,6 @@ interface BrowserPoolInfo { * @default false */ active: boolean, - - isRobotRun?: boolean; } /** @@ -48,29 +46,17 @@ export class BrowserPool { * @param browser remote browser instance * @param active states if the browser's instance is being actively used */ - public addRemoteBrowser = (id: string, browser: RemoteBrowser, active: boolean = false, isRobotRun: boolean = false): void => { + public addRemoteBrowser = (id: string, browser: RemoteBrowser, active: boolean = false): void => { this.pool = { ...this.pool, [id]: { browser, active, - isRobotRun }, } logger.log('debug', `Remote browser with id: ${id} added to the pool`); }; - public hasActiveRobotRun(): boolean { - return Object.values(this.pool).some(info => info.isRobotRun); - } - - public clearRobotRunState(id: string): void { - if (this.pool[id]) { - this.pool[id].isRobotRun = false; - logger.log('debug', `Robot run state cleared for browser ${id}`); - } - } - /** * Removes the remote browser instance from the pool. * @param id remote browser instance's id @@ -81,8 +67,6 @@ export class BrowserPool { logger.log('warn', `Remote browser with id: ${id} does not exist in the pool`); return false; } - - this.clearRobotRunState(id); delete (this.pool[id]); logger.log('debug', `Remote browser with id: ${id} deleted from the pool`); return true; diff --git a/server/src/browser-management/controller.ts b/server/src/browser-management/controller.ts index f589ce3f..24a677ce 100644 --- a/server/src/browser-management/controller.ts +++ b/server/src/browser-management/controller.ts @@ -59,7 +59,7 @@ export const createRemoteBrowserForRun = (userId: string): string => { async (socket: Socket) => { const browserSession = new RemoteBrowser(socket); await browserSession.initialize(userId); - browserPool.addRemoteBrowser(id, browserSession, true, true); + browserPool.addRemoteBrowser(id, browserSession, true); socket.emit('ready-for-run'); }); return id; diff --git a/server/src/routes/record.ts b/server/src/routes/record.ts index 17146173..51d3ff92 100644 --- a/server/src/routes/record.ts +++ b/server/src/routes/record.ts @@ -16,7 +16,6 @@ import stealthPlugin from 'puppeteer-extra-plugin-stealth'; import logger from "../logger"; import { getDecryptedProxyConfig } from './proxy'; import { requireSignIn } from '../middlewares/auth'; -import { browserPool } from '../server'; export const router = Router(); chromium.use(stealthPlugin()); @@ -34,17 +33,6 @@ router.all('/', requireSignIn, (req, res, next) => { next() // pass control to the next handler }) -router.use('/', requireSignIn, (req: AuthenticatedRequest, res: Response, next) => { - if (browserPool.hasActiveRobotRun()) { - logger.log('debug', 'Preventing browser initialization - robot run in progress'); - return res.status(403).json({ - error: 'Cannot initialize recording browser while a robot run is in progress' - }); - } - next(); -}); - - /** * GET endpoint for starting the remote browser recording session. * returns session's id diff --git a/server/src/workflow-management/classes/Interpreter.ts b/server/src/workflow-management/classes/Interpreter.ts index 661f58db..c8aec13c 100644 --- a/server/src/workflow-management/classes/Interpreter.ts +++ b/server/src/workflow-management/classes/Interpreter.ts @@ -332,8 +332,6 @@ export class WorkflowInterpreter { }, {}) } - this.socket.emit('run-completed', "success"); - logger.log('debug', `Interpretation finished`); this.clearState(); return result; diff --git a/src/pages/MainPage.tsx b/src/pages/MainPage.tsx index c8066951..b9a4f24f 100644 --- a/src/pages/MainPage.tsx +++ b/src/pages/MainPage.tsx @@ -68,14 +68,13 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) const readyForRunHandler = useCallback((browserId: string, runId: string) => { interpretStoredRecording(runId).then(async (interpretation: boolean) => { if (!aborted) { - // if (interpretation) { - // notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); - // } else { - // notify('success', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); - // // destroy the created browser - // await stopRecording(browserId); - // } - if (!interpretation) await stopRecording(browserId); + if (interpretation) { + notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); + } else { + notify('success', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); + // destroy the created browser + await stopRecording(browserId); + } } setRunningRecordingName(''); setCurrentInterpretationLog(''); @@ -90,12 +89,6 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) const handleRunRecording = useCallback((settings: RunSettings) => { createRunForStoredRecording(runningRecordingId, settings).then(({ browserId, runId }: CreateRunResponse) => { - localStorage.setItem('runInfo', JSON.stringify({ - browserId, - runId, - recordingName: runningRecordingName - })); - setIds({ browserId, runId }); const socket = io(`${apiUrl}/${browserId}`, { @@ -105,18 +98,6 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) setSockets(sockets => [...sockets, socket]); socket.on('ready-for-run', () => readyForRunHandler(browserId, runId)); socket.on('debugMessage', debugMessageHandler); - - socket.on('run-completed', (status) => { - if (status === 'success') { - notify('success', t('main_page.notifications.interpretation_success', { name: runningRecordingName })); - } else { - notify('error', t('main_page.notifications.interpretation_failed', { name: runningRecordingName })); - } - setRunningRecordingName(''); - setCurrentInterpretationLog(''); - setRerenderRuns(true); - }); - setContent('runs'); if (browserId) { notify('info', t('main_page.notifications.run_started', { name: runningRecordingName })); @@ -127,7 +108,6 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) return (socket: Socket, browserId: string, runId: string) => { socket.off('ready-for-run', () => readyForRunHandler(browserId, runId)); socket.off('debugMessage', debugMessageHandler); - socket.off('run-completed'); } }, [runningRecordingName, sockets, ids, readyForRunHandler, debugMessageHandler]) @@ -142,49 +122,6 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) }); } - useEffect(() => { - const storedRunInfo = localStorage.getItem('runInfo'); - console.log('storedRunInfo', storedRunInfo); - - if (storedRunInfo) { - // Parse the stored info - const { browserId, runId, recordingName } = JSON.parse(storedRunInfo); - - // Reconnect to the specific browser's namespace - setIds({ browserId, runId }); - const socket = io(`${apiUrl}/${browserId}`, { - transports: ["websocket"], - rejectUnauthorized: false - }); - - // Update component state with stored info - setRunningRecordingName(recordingName); - setSockets(sockets => [...sockets, socket]); - - // Set up event listeners - socket.on('ready-for-run', () => readyForRunHandler(browserId, runId)); - socket.on('debugMessage', debugMessageHandler); - socket.on('run-completed', (status) => { - if (status === 'success') { - notify('success', t('main_page.notifications.interpretation_success', { name: recordingName })); - } else { - notify('error', t('main_page.notifications.interpretation_failed', { name: recordingName })); - } - setRunningRecordingName(''); - setCurrentInterpretationLog(''); - setRerenderRuns(true); - localStorage.removeItem('runInfo'); // Clean up stored info - }); - - // Cleanup function - return () => { - socket.off('ready-for-run', () => readyForRunHandler(browserId, runId)); - socket.off('debugMessage', debugMessageHandler); - socket.off('run-completed'); - }; - } - }, []); - const DisplayContent = () => { switch (content) { case 'robots': From e0deccafde1bb6a5608364158c21240b86c3cf7c Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 12:43:06 +0530 Subject: [PATCH 101/138] feat: add robotId cookie and redirect --- server/src/routes/auth.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 837fcd8a..49af7090 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -380,11 +380,19 @@ router.get( httpOnly: false, maxAge: 60000, }); // 1-minute expiration - res.cookie("robot_auth_message", "Robot successfully authenticated", { + // res.cookie("robot_auth_message", "Robot successfully authenticated", { + // httpOnly: false, + // maxAge: 60000, + // }); + res.cookie('robot_auth_robotId', robotId, { httpOnly: false, maxAge: 60000, }); - res.redirect(`${process.env.PUBLIC_URL}/robots/${robotId}/integrate` as string || `http://localhost:5173/robots/${robotId}/integrate`); + + const baseUrl = process.env.PUBLIC_URL || "http://localhost:5173"; + const redirectUrl = `${baseUrl}/robots/`; + + res.redirect(redirectUrl); } catch (error: any) { res.status(500).json({ message: `Google OAuth error: ${error.message}` }); } From 160777926870ffea362fa54081ae83ada265f9fc Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 12:43:57 +0530 Subject: [PATCH 102/138] feat: check for cookie and open modal --- src/components/robot/Recordings.tsx | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/components/robot/Recordings.tsx b/src/components/robot/Recordings.tsx index 9ddfccc7..89fc3411 100644 --- a/src/components/robot/Recordings.tsx +++ b/src/components/robot/Recordings.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import { RecordingsTable } from "./RecordingsTable"; import { Grid } from "@mui/material"; import { RunSettings, RunSettingsModal } from "../run/RunSettings"; @@ -8,6 +8,7 @@ import { RobotSettingsModal } from "./RobotSettings"; import { RobotEditModal } from "./RobotEdit"; import { RobotDuplicationModal } from "./RobotDuplicate"; import { useNavigate, useLocation, useParams } from "react-router-dom"; +import { useGlobalInfoStore } from "../../context/globalInfo"; interface RecordingsProps { handleEditRecording: (id: string, fileName: string) => void; @@ -26,6 +27,7 @@ export const Recordings = ({ const location = useLocation(); const { selectedRecordingId } = useParams(); const [params, setParams] = useState([]); + const { notify } = useGlobalInfoStore(); const handleNavigate = (path: string, id: string, name: string, params: string[]) => { setParams(params); @@ -39,6 +41,31 @@ export const Recordings = ({ navigate("/robots"); // Navigate back to the main robots page }; + useEffect(() => { + // Helper function to get and clear a cookie + const getAndClearCookie = (name: string) => { + const value = document.cookie + .split('; ') + .find(row => row.startsWith(`${name}=`)) + ?.split('=')[1]; + + if (value) { + document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`; + } + + return value; + }; + + const authStatus = getAndClearCookie('robot_auth_status'); + const robotId = getAndClearCookie('robot_auth_robotId'); + + if (authStatus === 'success' && robotId) { + notify(authStatus, "Robot successfully authenticated"); + + handleNavigate(`/robots/${robotId}/integrate`, robotId, "", []);'' + } + }, []); + // Determine which modal to open based on the current route const getCurrentModal = () => { const currentPath = location.pathname; From 1d4dbf8a45c0d4bd8f2ec4d5eadc58910186b32b Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 12:44:51 +0530 Subject: [PATCH 103/138] feat: rm cookie logic --- .../integration/IntegrationSettings.tsx | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/src/components/integration/IntegrationSettings.tsx b/src/components/integration/IntegrationSettings.tsx index 835221ca..31c93368 100644 --- a/src/components/integration/IntegrationSettings.tsx +++ b/src/components/integration/IntegrationSettings.tsx @@ -29,20 +29,6 @@ export interface IntegrationSettings { data: string; } -// Helper functions to replace js-cookie functionality -const getCookie = (name: string): string | null => { - const value = `; ${document.cookie}`; - const parts = value.split(`; ${name}=`); - if (parts.length === 2) { - return parts.pop()?.split(';').shift() || null; - } - return null; -}; - -const removeCookie = (name: string): void => { - document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`; -}; - export const IntegrationSettingsModal = ({ isOpen, handleStart, @@ -154,17 +140,6 @@ export const IntegrationSettingsModal = ({ }; useEffect(() => { - // Check if there is a success message in cookies - const status = getCookie("robot_auth_status"); - const message = getCookie("robot_auth_message"); - - if (status === "success" && message) { - notify("success", message); - // Clear the cookies after reading - removeCookie("robot_auth_status"); - removeCookie("robot_auth_message"); - } - // Check if we're on the callback URL const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get("code"); From 9f406c79a7675de1de812826c5cf8d7a0ea5eec5 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 12:56:19 +0530 Subject: [PATCH 104/138] feat: add translation for recording --- src/components/robot/Recordings.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/robot/Recordings.tsx b/src/components/robot/Recordings.tsx index 89fc3411..e63f5e1c 100644 --- a/src/components/robot/Recordings.tsx +++ b/src/components/robot/Recordings.tsx @@ -9,6 +9,7 @@ import { RobotEditModal } from "./RobotEdit"; import { RobotDuplicationModal } from "./RobotDuplicate"; import { useNavigate, useLocation, useParams } from "react-router-dom"; import { useGlobalInfoStore } from "../../context/globalInfo"; +import { useTranslation } from "react-i18next"; interface RecordingsProps { handleEditRecording: (id: string, fileName: string) => void; @@ -28,6 +29,7 @@ export const Recordings = ({ const { selectedRecordingId } = useParams(); const [params, setParams] = useState([]); const { notify } = useGlobalInfoStore(); + const { t } = useTranslation(); const handleNavigate = (path: string, id: string, name: string, params: string[]) => { setParams(params); @@ -60,7 +62,7 @@ export const Recordings = ({ const robotId = getAndClearCookie('robot_auth_robotId'); if (authStatus === 'success' && robotId) { - notify(authStatus, "Robot successfully authenticated"); + notify(authStatus, t("recordingtable.notifications.auth_success")); handleNavigate(`/robots/${robotId}/integrate`, robotId, "", []);'' } From 335bb379b6329b65b773bc9f5bcbfe1d5ad20a31 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 12:56:58 +0530 Subject: [PATCH 105/138] feat: add translation for integrate notification --- 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, 10 insertions(+), 5 deletions(-) diff --git a/public/locales/de.json b/public/locales/de.json index 21b71313..48422b0a 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -41,7 +41,8 @@ "duplicate": "Duplizieren", "notifications": { "delete_warning": "Roboter kann nicht gelöscht werden, da zugehörige Ausführungen vorhanden sind", - "delete_success": "Roboter erfolgreich gelöscht" + "delete_success": "Roboter erfolgreich gelöscht", + "auth_success": "Roboter erfolgreich authentifiziert" } }, "mainmenu": { diff --git a/public/locales/en.json b/public/locales/en.json index a51f6c65..cd63195e 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -42,7 +42,8 @@ "search":"Search Robots...", "notifications": { "delete_warning": "Cannot delete robot as it has associated runs", - "delete_success": "Robot deleted successfully" + "delete_success": "Robot deleted successfully", + "auth_success": "Robot successfully authenticated" } }, "mainmenu":{ diff --git a/public/locales/es.json b/public/locales/es.json index 8ef9b8bf..63d6dd02 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -42,7 +42,8 @@ "search": "Buscar robots...", "notifications": { "delete_warning": "No se puede eliminar el robot ya que tiene ejecuciones asociadas", - "delete_success": "Robot eliminado exitosamente" + "delete_success": "Robot eliminado exitosamente", + "auth_success": "Robot autenticado exitosamente" } }, "mainmenu": { diff --git a/public/locales/ja.json b/public/locales/ja.json index 03f91cf6..f2489ff0 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -42,7 +42,8 @@ "search": "ロボットを検索...", "notifications": { "delete_warning": "関連する実行があるため、ロボットを削除できません", - "delete_success": "ロボットが正常に削除されました" + "delete_success": "ロボットが正常に削除されました", + "auth_success": "ロボットの認証に成功しました" } }, "mainmenu": { diff --git a/public/locales/zh.json b/public/locales/zh.json index 41e3a762..de7e655a 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -42,7 +42,8 @@ "search": "搜索机器人...", "notifications": { "delete_warning": "无法删除机器人,因为它有关联的运行记录", - "delete_success": "机器人删除成功" + "delete_success": "机器人删除成功", + "auth_success": "机器人认证成功" } }, "mainmenu": { From ddcbff75bcc78d616d6ccb34a5a7ff885274f297 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:42:33 +0530 Subject: [PATCH 106/138] feat: username --- src/components/robot/RobotEdit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 035165ba..9e60202c 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -281,7 +281,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {/* Render username credentials */} {renderCredentialFields( credentialGroups.usernames, - t('Username Credentials'), + t('Username'), 'text' // Always show usernames as text )} From 9a7b5d0a8b7f96414dfef2a87ab5da5cdd1cdaaf Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:43:05 +0530 Subject: [PATCH 107/138] feat: email --- src/components/robot/RobotEdit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 9e60202c..7f6b8693 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -288,7 +288,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {/* Render email credentials */} {renderCredentialFields( credentialGroups.emails, - t('Email Credentials'), + t('Email'), 'text' // Always show emails as text )} From 4d4d4110805541bf06e39dc2e4536aa118d5aa0c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:43:18 +0530 Subject: [PATCH 108/138] feat: password --- src/components/robot/RobotEdit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 7f6b8693..02b6f43f 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -295,7 +295,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {/* Render password credentials */} {renderCredentialFields( credentialGroups.passwords, - t('Password Credentials'), + t('Password'), 'password' // Use password masking )} From 1566789a647f1f48c997ab3ae7c26268bbfd899f Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:43:30 +0530 Subject: [PATCH 109/138] feat: other --- src/components/robot/RobotEdit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 02b6f43f..a62d8e2b 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -302,7 +302,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {/* Render other credentials */} {renderCredentialFields( credentialGroups.others, - t('Other Credentials'), + t('Other'), 'text' // Show other credentials as text )} From 438da828c0a809b0394aee1294d65ca349c14718 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:44:05 +0530 Subject: [PATCH 110/138] chore: cleanup --- src/components/robot/RobotEdit.tsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index a62d8e2b..45397ff8 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -278,32 +278,28 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const renderAllCredentialFields = () => { return ( <> - {/* Render username credentials */} {renderCredentialFields( credentialGroups.usernames, t('Username'), - 'text' // Always show usernames as text + 'text' )} - {/* Render email credentials */} {renderCredentialFields( credentialGroups.emails, t('Email'), - 'text' // Always show emails as text + 'text' )} - {/* Render password credentials */} {renderCredentialFields( credentialGroups.passwords, t('Password'), - 'password' // Use password masking + 'password' )} - {/* Render other credentials */} {renderCredentialFields( credentialGroups.others, t('Other'), - 'text' // Show other credentials as text + 'text' )} ); From cf5107f7c89259fed1aa84391ad13fa279d43d61 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:49:21 +0530 Subject: [PATCH 111/138] feat: use input index instead of selector as label --- src/components/robot/RobotEdit.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 45397ff8..1c070d45 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -313,7 +313,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {headerText} - {selectors.map((selector) => { + {selectors.map((selector, index) => { const isVisible = showPasswords[selector]; return ( @@ -321,7 +321,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin key={selector} // The type changes based on visibility state type={isVisible ? 'text' : 'password'} - label={`Credential for ${selector}`} + label={`Input ${index + 1}`} value={credentials[selector]?.value || ''} onChange={(e) => handleCredentialChange(selector, e.target.value)} style={{ marginBottom: '20px' }} From 5f0427232d888dea04b58042b4a91369186b8a3f Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:50:12 +0530 Subject: [PATCH 112/138] feat: show input aria-labe; --- src/components/robot/RobotEdit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 1c070d45..dd511641 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -330,7 +330,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin endAdornment: ( handleClickShowPassword(selector)} edge="end" // Optional: disable if field is empty From a06c6a59ec869c1e4197ba397d384659652cc033 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:50:27 +0530 Subject: [PATCH 113/138] chore: lint --- src/components/robot/RobotEdit.tsx | 70 +++++++++++++++--------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index dd511641..736086c1 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -79,22 +79,22 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const [robot, setRobot] = useState(null); const [credentials, setCredentials] = useState({}); const { recordingId, notify } = useGlobalInfoStore(); - const [credentialGroups, setCredentialGroups] = useState({ - passwords: [], + const [credentialGroups, setCredentialGroups] = useState({ + passwords: [], emails: [], usernames: [], - others: [] + others: [] }); const [showPasswords, setShowPasswords] = useState({}); const isEmailPattern = (value: string): boolean => { return value.includes('@'); }; - + const isUsernameSelector = (selector: string): boolean => { - return selector.toLowerCase().includes('username') || - selector.toLowerCase().includes('user') || - selector.toLowerCase().includes('email'); + return selector.toLowerCase().includes('username') || + selector.toLowerCase().includes('user') || + selector.toLowerCase().includes('email'); }; const determineCredentialType = (selector: string, info: CredentialInfo): 'password' | 'email' | 'username' | 'other' => { @@ -102,20 +102,20 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin if (info.type === 'password') { return 'password'; } - + // Check for email patterns in the value or selector if (isEmailPattern(info.value) || selector.toLowerCase().includes('email')) { return 'email'; } - + // Check for username patterns in the selector if (isUsernameSelector(selector)) { return 'username'; } - + return 'other'; }; - + useEffect(() => { if (isOpen) { getRobot(); @@ -132,32 +132,32 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const extractInitialCredentials = (workflow: any[]): Credentials => { const credentials: Credentials = {}; - + // Helper function to check if a character is printable const isPrintableCharacter = (char: string): boolean => { return char.length === 1 && !!char.match(/^[\x20-\x7E]$/); }; - + // Process each step in the workflow workflow.forEach(step => { if (!step.what) return; - + // Keep track of the current input field being processed let currentSelector = ''; let currentValue = ''; let currentType = ''; - + // Process actions in sequence to maintain correct text state step.what.forEach((action: any) => { if ( - (action.action === 'type' || action.action === 'press') && - action.args?.length >= 2 && + (action.action === 'type' || action.action === 'press') && + action.args?.length >= 2 && typeof action.args[1] === 'string' ) { const selector: string = action.args[0]; const character: string = action.args[1]; const inputType: string = action.args[2] || ''; - + // If we're dealing with a new selector, store the previous one if (currentSelector && selector !== currentSelector) { if (!credentials[currentSelector]) { @@ -169,14 +169,14 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin credentials[currentSelector].value = currentValue; } } - + // Update current tracking variables if (selector !== currentSelector) { currentSelector = selector; currentValue = credentials[selector]?.value || ''; currentType = inputType || credentials[selector]?.type || ''; } - + // Handle different types of key actions if (character === 'Backspace') { // Remove the last character when backspace is pressed @@ -188,7 +188,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin // Note: We ignore other special keys like 'Shift', 'Enter', etc. } }); - + // Store the final state of the last processed selector if (currentSelector) { credentials[currentSelector] = { @@ -197,14 +197,14 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin }; } }); - + return credentials; }; const groupCredentialsByType = (credentials: Credentials): GroupedCredentials => { return Object.entries(credentials).reduce((acc: GroupedCredentials, [selector, info]) => { const credentialType = determineCredentialType(selector, info); - + switch (credentialType) { case 'password': acc.passwords.push(selector); @@ -218,7 +218,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin default: acc.others.push(selector); } - + return acc; }, { passwords: [], emails: [], usernames: [], others: [] }); }; @@ -279,25 +279,25 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return ( <> {renderCredentialFields( - credentialGroups.usernames, + credentialGroups.usernames, t('Username'), 'text' )} - + {renderCredentialFields( - credentialGroups.emails, + credentialGroups.emails, t('Email'), 'text' )} - + {renderCredentialFields( - credentialGroups.passwords, + credentialGroups.passwords, t('Password'), 'password' )} - + {renderCredentialFields( - credentialGroups.others, + credentialGroups.others, t('Other'), 'text' )} @@ -307,15 +307,15 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const renderCredentialFields = (selectors: string[], headerText: string, defaultType: 'text' | 'password' = 'text') => { if (selectors.length === 0) return null; - + return ( <> - + {headerText} {selectors.map((selector, index) => { const isVisible = showPasswords[selector]; - + return ( handleRobotNameChange(e.target.value)} style={{ marginBottom: '20px' }} /> - + {robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== undefined && ( Date: Sat, 25 Jan 2025 15:57:23 +0530 Subject: [PATCH 114/138] feat: !display header text --- src/components/robot/RobotEdit.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 736086c1..7bfd0fe6 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -310,9 +310,9 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return ( <> - + {/* {headerText} - + */} {selectors.map((selector, index) => { const isVisible = showPasswords[selector]; @@ -321,7 +321,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin key={selector} // The type changes based on visibility state type={isVisible ? 'text' : 'password'} - label={`Input ${index + 1}`} + label={`Text ${selector}`} value={credentials[selector]?.value || ''} onChange={(e) => handleCredentialChange(selector, e.target.value)} style={{ marginBottom: '20px' }} From 88b2aef2c8c237b2646b0873a07a4d96f9d30a10 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 15:59:33 +0530 Subject: [PATCH 115/138] feat: set label based on header text --- src/components/robot/RobotEdit.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 7bfd0fe6..1e53a433 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -321,7 +321,8 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin key={selector} // The type changes based on visibility state type={isVisible ? 'text' : 'password'} - label={`Text ${selector}`} + // label={`Text ${selector}`} + label={`${headerText}`} value={credentials[selector]?.value || ''} onChange={(e) => handleCredentialChange(selector, e.target.value)} style={{ marginBottom: '20px' }} From 7a017f5bd80038a4964ed47f9a8c4646b409a183 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:09:33 +0530 Subject: [PATCH 116/138] feat: detect input type password --- src/components/robot/RobotEdit.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 1e53a433..d3e146ad 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -158,6 +158,11 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const character: string = action.args[1]; const inputType: string = action.args[2] || ''; + // Detect `input[type="password"]` + if (!currentType && inputType.toLowerCase() === 'password') { + currentType = 'password'; + } + // If we're dealing with a new selector, store the previous one if (currentSelector && selector !== currentSelector) { if (!credentials[currentSelector]) { From c46b3e2b755ba424e4d250fb091b3439c59431d0 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:12:45 +0530 Subject: [PATCH 117/138] feat: detect password based on selector --- src/components/robot/RobotEdit.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index d3e146ad..23b43f74 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -99,7 +99,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const determineCredentialType = (selector: string, info: CredentialInfo): 'password' | 'email' | 'username' | 'other' => { // Check for password type first - if (info.type === 'password') { + if (info.type === 'password' || selector.toLowerCase().includes('password')) { return 'password'; } @@ -162,7 +162,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin if (!currentType && inputType.toLowerCase() === 'password') { currentType = 'password'; } - + // If we're dealing with a new selector, store the previous one if (currentSelector && selector !== currentSelector) { if (!credentials[currentSelector]) { From c8add28859905ac4081af9b75c873e1ae17df8de Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:13:08 +0530 Subject: [PATCH 118/138] chore: cleanup --- src/components/robot/RobotEdit.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 23b43f74..f6dff08a 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -98,21 +98,15 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin }; const determineCredentialType = (selector: string, info: CredentialInfo): 'password' | 'email' | 'username' | 'other' => { - // Check for password type first if (info.type === 'password' || selector.toLowerCase().includes('password')) { return 'password'; } - - // Check for email patterns in the value or selector if (isEmailPattern(info.value) || selector.toLowerCase().includes('email')) { return 'email'; } - - // Check for username patterns in the selector if (isUsernameSelector(selector)) { return 'username'; } - return 'other'; }; From 3918a6e558de13927c4ab1289f7a0768b9008224 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:17:48 +0530 Subject: [PATCH 119/138] feat: input label based on headerText --- src/components/robot/RobotEdit.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index f6dff08a..e84168fb 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -321,7 +321,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin // The type changes based on visibility state type={isVisible ? 'text' : 'password'} // label={`Text ${selector}`} - label={`${headerText}`} + label={headerText === 'Other' ? `${`Input`} ${index + 1}` : headerText} value={credentials[selector]?.value || ''} onChange={(e) => handleCredentialChange(selector, e.target.value)} style={{ marginBottom: '20px' }} From 8e5181ec462cc120344356f4dc8a27655bdcbc81 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:18:10 +0530 Subject: [PATCH 120/138] chore: cleanup --- src/components/robot/RobotEdit.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index e84168fb..f9d0752a 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -318,22 +318,18 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return ( handleCredentialChange(selector, e.target.value)} style={{ marginBottom: '20px' }} InputProps={{ - // Now showing visibility toggle for all fields endAdornment: ( handleClickShowPassword(selector)} edge="end" - // Optional: disable if field is empty disabled={!credentials[selector]?.value} > {isVisible ? : } From e4047b1f659b84287a785451701c3f962aca9fb7 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:21:27 +0530 Subject: [PATCH 121/138] feat: edit input texts --- src/components/robot/RobotEdit.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index f9d0752a..a344268a 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -423,6 +423,9 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {(robot.isLogin || Object.keys(credentials).length > 0) && ( <> + + {t('Input Texts')} + {renderAllCredentialFields()} )} From ee0617cbd593ab6098b943b5f9ddb0a9d9c0f1cd Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:21:56 +0530 Subject: [PATCH 122/138] chore: lint --- src/components/robot/RobotEdit.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index a344268a..07cc5b38 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -423,9 +423,9 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin {(robot.isLogin || Object.keys(credentials).length > 0) && ( <> - - {t('Input Texts')} - + + {t('Input Texts')} + {renderAllCredentialFields()} )} From fb3dd4e23f74bdd4452ec5de7c229111295a0d37 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:34:11 +0530 Subject: [PATCH 123/138] chore: core 0.0.10 --- 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 d403360a..5b732a6b 100644 --- a/maxun-core/package.json +++ b/maxun-core/package.json @@ -1,6 +1,6 @@ { "name": "maxun-core", - "version": "0.0.9", + "version": "0.0.10", "description": "Core package for Maxun, responsible for data extraction", "main": "build/index.js", "typings": "build/index.d.ts", From a831e54d4af79310dced01c046bca59115e959f5 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 16:38:30 +0530 Subject: [PATCH 124/138] feat: order the input field logic --- .../workflow-management/classes/Generator.ts | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/server/src/workflow-management/classes/Generator.ts b/server/src/workflow-management/classes/Generator.ts index 108c1e8b..a36e1ce8 100644 --- a/server/src/workflow-management/classes/Generator.ts +++ b/server/src/workflow-management/classes/Generator.ts @@ -354,40 +354,6 @@ export class WorkflowGenerator { const elementInfo = await getElementInformation(page, coordinates, '', false); console.log("Element info: ", elementInfo); - if ((elementInfo?.tagName === 'INPUT' || elementInfo?.tagName === 'TEXTAREA') && selector) { - // Calculate the exact position within the element - const elementPos = await page.evaluate((selector) => { - const element = document.querySelector(selector); - if (!element) return null; - const rect = element.getBoundingClientRect(); - return { - x: rect.left, - y: rect.top - }; - }, selector); - - if (elementPos) { - const relativeX = coordinates.x - elementPos.x; - const relativeY = coordinates.y - elementPos.y; - - const pair: WhereWhatPair = { - where, - what: [{ - action: 'click', - args: [selector, { position: { x: relativeX, y: relativeY } }] - }] - }; - - if (selector) { - this.generatedData.lastUsedSelector = selector; - this.generatedData.lastAction = 'click'; - } - - await this.addPairToWorkflowAndNotifyClient(pair, page); - return; - } - } - // Check if clicked element is a select dropdown const isDropdown = elementInfo?.tagName === 'SELECT'; @@ -459,6 +425,40 @@ export class WorkflowGenerator { return; } + if ((elementInfo?.tagName === 'INPUT' || elementInfo?.tagName === 'TEXTAREA') && selector) { + // Calculate the exact position within the element + const elementPos = await page.evaluate((selector) => { + const element = document.querySelector(selector); + if (!element) return null; + const rect = element.getBoundingClientRect(); + return { + x: rect.left, + y: rect.top + }; + }, selector); + + if (elementPos) { + const relativeX = coordinates.x - elementPos.x; + const relativeY = coordinates.y - elementPos.y; + + const pair: WhereWhatPair = { + where, + what: [{ + action: 'click', + args: [selector, { position: { x: relativeX, y: relativeY } }] + }] + }; + + if (selector) { + this.generatedData.lastUsedSelector = selector; + this.generatedData.lastAction = 'click'; + } + + await this.addPairToWorkflowAndNotifyClient(pair, page); + return; + } + } + //const element = await getElementMouseIsOver(page, coordinates); //logger.log('debug', `Element: ${JSON.stringify(element, null, 2)}`); if (selector) { From befeab968ac2c2cd4b057fbdb965c1ecdf7ade5d Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:41:24 +0530 Subject: [PATCH 125/138] chore: upgrade core 0.0.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5dae78a2..13754dce 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "lodash": "^4.17.21", "loglevel": "^1.8.0", "loglevel-plugin-remote": "^0.6.8", - "maxun-core": "^0.0.9", + "maxun-core": "^0.0.10", "minio": "^8.0.1", "moment-timezone": "^0.5.45", "node-cron": "^3.0.3", From 2987865a32396b7ad72d4944ea27192c3636ba97 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sat, 25 Jan 2025 16:41:40 +0530 Subject: [PATCH 126/138] chore: upgrade version to 0.0.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 13754dce..768b970f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "maxun", - "version": "0.0.7", + "version": "0.0.8", "author": "Maxun", "license": "AGPL-3.0-or-later", "dependencies": { From 38b72cdb5787c3a69fb02a99c544669c51b03635 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 17:28:53 +0530 Subject: [PATCH 127/138] feat: rm isLogin field --- server/src/models/Robot.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/server/src/models/Robot.ts b/server/src/models/Robot.ts index 0cd11b51..3b2717d6 100644 --- a/server/src/models/Robot.ts +++ b/server/src/models/Robot.ts @@ -26,7 +26,6 @@ interface RobotAttributes { google_access_token?: string | null; google_refresh_token?: string | null; schedule?: ScheduleConfig | null; - isLogin?: boolean; } interface ScheduleConfig { @@ -55,7 +54,6 @@ class Robot extends Model implements R public google_access_token!: string | null; public google_refresh_token!: string | null; public schedule!: ScheduleConfig | null; - public isLogin!: boolean; } Robot.init( @@ -101,11 +99,6 @@ Robot.init( type: DataTypes.JSONB, allowNull: true, }, - isLogin: { - type: DataTypes.BOOLEAN, - allowNull: false, - defaultValue: false, - }, }, { sequelize, From 0bc8856f3e8a4d57a5dff2d5ad89d22e6ce32542 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 17:29:33 +0530 Subject: [PATCH 128/138] feat: rm isLogin field in routes --- server/src/routes/storage.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index fb587d17..01f1ca6b 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -350,7 +350,6 @@ router.post('/recordings/:id/duplicate', requireSignIn, async (req: Authenticate updatedAt: currentTimestamp, }, recording: { ...originalRobot.recording, workflow }, - isLogin: originalRobot.isLogin, google_sheet_email: null, google_sheet_name: null, google_sheet_id: null, From 09d2088cbfea1bac0f49a41713a03808ce8bb193 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 17:30:03 +0530 Subject: [PATCH 129/138] feat: rm isLogin for save recording --- src/components/recorder/SaveRecording.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/recorder/SaveRecording.tsx b/src/components/recorder/SaveRecording.tsx index c6b5687b..4a2d0ba4 100644 --- a/src/components/recorder/SaveRecording.tsx +++ b/src/components/recorder/SaveRecording.tsx @@ -22,7 +22,7 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { const [recordingName, setRecordingName] = useState(fileName); const [waitingForSave, setWaitingForSave] = useState(false); - const { browserId, setBrowserId, notify, recordings, isLogin } = useGlobalInfoStore(); + const { browserId, setBrowserId, notify, recordings } = useGlobalInfoStore(); const { socket } = useSocketStore(); const { state, dispatch } = useContext(AuthContext); const { user } = state; @@ -59,7 +59,7 @@ export const SaveRecording = ({ fileName }: SaveRecordingProps) => { // releases resources and changes the view for main page by clearing the global browserId const saveRecording = async () => { if (user) { - const payload = { fileName: recordingName, userId: user.id, isLogin: isLogin }; + const payload = { fileName: recordingName, userId: user.id }; socket?.emit('save', payload); setWaitingForSave(true); console.log(`Saving the recording as ${recordingName} for userId ${user.id}`); From 7733c5bff566ba764b382d57ec81f27914e5d62d Mon Sep 17 00:00:00 2001 From: Rohit Date: Sat, 25 Jan 2025 17:30:38 +0530 Subject: [PATCH 130/138] feat: rm Login checkbox --- src/components/robot/RecordingsTable.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index a7594b08..63968824 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -124,8 +124,6 @@ export const RecordingsTable = ({ setInitialUrl, recordingUrl, setRecordingUrl, - isLogin, - setIsLogin, recordingName, setRecordingName, recordingId, @@ -366,18 +364,6 @@ export const RecordingsTable = ({ style={{ marginBottom: '10px', marginTop: '20px' }} /> - setIsLogin(e.target.checked)} - color="primary" - /> - } - label={t('recordingtable.modal.login_title')} - style={{ marginBottom: '10px' }} - /> -