From f3d49f175cd9586d7e060704014e5d70be668fe1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 14 Jan 2025 19:09:24 +0530 Subject: [PATCH 001/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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/174] 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 1ae738ebc2cf55366ea42ee58ce823b1661d008d Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 19:12:31 +0530 Subject: [PATCH 088/174] feat: memoize recordings table --- src/components/robot/RecordingsTable.tsx | 309 +++++++++++++---------- 1 file changed, 175 insertions(+), 134 deletions(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index e7409b89..4d928289 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -8,7 +8,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 { useEffect } from "react"; +import { memo, useCallback, useEffect, useMemo } 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, RadioGroup, FormControlLabel, Radio } from "@mui/material"; @@ -52,6 +52,64 @@ interface RecordingsTableProps { handleDuplicateRobot: (id: string, name: string, params: string[]) => void; } +// Virtualized row component for efficient rendering +const TableRowMemoized = memo(({ row, columns, handlers }: any) => { + return ( + + {columns.map((column: Column) => { + const value: any = row[column.id]; + if (value !== undefined) { + return ( + + {value} + + ); + } else { + switch (column.id) { + case 'interpret': + return ( + + handlers.handleRunRecording(row.id, row.name, row.params || [])} /> + + ); + case 'schedule': + return ( + + handlers.handleScheduleRecording(row.id, row.name, row.params || [])} /> + + ); + case 'integrate': + return ( + + handlers.handleIntegrateRecording(row.id, row.name, row.params || [])} /> + + ); + case 'options': + return ( + + handlers.handleEditRobot(row.id, row.name, row.params || [])} + handleDuplicate={() => handlers.handleDuplicateRobot(row.id, row.name, row.params || [])} + handleDelete={() => handlers.handleDelete(row.id)} + /> + + ); + case 'settings': + return ( + + handlers.handleSettingsRecording(row.id, row.name, row.params || [])} /> + + ); + default: + return null; + } + } + })} + + ); +}); + + export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording, handleEditRobot, handleDuplicateRobot }: RecordingsTableProps) => { const { t } = useTranslation(); const [page, setPage] = React.useState(0); @@ -59,83 +117,77 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl const [rows, setRows] = React.useState([]); const [isModalOpen, setModalOpen] = React.useState(false); const [searchTerm, setSearchTerm] = React.useState(''); + const [isLoading, setIsLoading] = React.useState(true); - const columns: readonly Column[] = [ + const columns = useMemo(() => [ { id: 'interpret', label: t('recordingtable.run'), minWidth: 80 }, { id: 'name', label: t('recordingtable.name'), minWidth: 80 }, - { - id: 'schedule', - label: t('recordingtable.schedule'), - minWidth: 80, - }, - { - id: 'integrate', - label: t('recordingtable.integrate'), - minWidth: 80, - }, - { - id: 'settings', - label: t('recordingtable.settings'), - minWidth: 80, - }, - { - id: 'options', - label: t('recordingtable.options'), - minWidth: 80, - }, - ]; + { id: 'schedule', label: t('recordingtable.schedule'), minWidth: 80 }, + { id: 'integrate', label: t('recordingtable.integrate'), minWidth: 80 }, + { id: 'settings', label: t('recordingtable.settings'), minWidth: 80 }, + { id: 'options', label: t('recordingtable.options'), minWidth: 80 }, + ], [t]); const { notify, setRecordings, browserId, setBrowserId, setInitialUrl, recordingUrl, setRecordingUrl, isLogin, setIsLogin, recordingName, setRecordingName, recordingId, setRecordingId } = useGlobalInfoStore(); const navigate = useNavigate(); - const handleChangePage = (event: unknown, newPage: number) => { + const handleChangePage = useCallback((event: unknown, newPage: number) => { setPage(newPage); - }; + }, []); const handleChangeRowsPerPage = (event: React.ChangeEvent) => { setRowsPerPage(+event.target.value); setPage(0); }; - const handleSearchChange = (event: React.ChangeEvent) => { + const handleSearchChange = useCallback((event: React.ChangeEvent) => { setSearchTerm(event.target.value); setPage(0); - }; + }, []); - const fetchRecordings = async () => { - const recordings = await getStoredRecordings(); - if (recordings) { - const parsedRows: Data[] = []; - recordings.map((recording: any, index: number) => { - if (recording && recording.recording_meta) { - parsedRows.push({ - id: index, - ...recording.recording_meta, - content: recording.recording - }); - } - }); - setRecordings(parsedRows.map((recording) => recording.name)); - setRows(parsedRows); - } else { - console.log('No recordings found.'); + const fetchRecordings = useCallback(async () => { + setIsLoading(true); + try { + const recordings = await getStoredRecordings(); + if (recordings) { + const parsedRows = recordings + .map((recording: any, index: number) => { + if (recording?.recording_meta) { + return { + id: index, + ...recording.recording_meta, + content: recording.recording + }; + } + return null; + }) + .filter(Boolean); + + setRecordings(parsedRows.map((recording) => recording.name)); + setRows(parsedRows); + } + } catch (error) { + console.error('Error fetching recordings:', error); + notify('error', t('recordingtable.notifications.fetch_error')); + } finally { + setIsLoading(false); } - } + }, [setRecordings, notify, t]); - const handleNewRecording = async () => { + const handleNewRecording = useCallback(async () => { if (browserId) { setBrowserId(null); await stopRecording(browserId); } setModalOpen(true); - }; + }, [browserId]); - const handleStartRecording = () => { + const handleStartRecording = useCallback(() => { setBrowserId('new-recording'); setRecordingName(''); setRecordingId(''); navigate('/recording'); - } + }, [navigate]); const startRecording = () => { setModalOpen(false); @@ -151,14 +203,61 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl if (rows.length === 0) { fetchRecordings(); } - }, []); + }, [fetchRecordings]); + function useDebounce(value: T, delay: number): T { + const [debouncedValue, setDebouncedValue] = React.useState(value); + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => { + clearTimeout(handler); + }; + }, [value, delay]); + + return debouncedValue; + } + + const debouncedSearchTerm = useDebounce(searchTerm, 300); // Filter rows based on search term - const filteredRows = rows.filter((row) => - row.name.toLowerCase().includes(searchTerm.toLowerCase()) - ); + const filteredRows = useMemo(() => { + const searchLower = searchTerm.toLowerCase(); + return searchTerm + ? rows.filter(row => row.name.toLowerCase().includes(searchLower)) + : rows; + }, [rows, debouncedSearchTerm]); + const visibleRows = useMemo(() => { + const start = page * rowsPerPage; + return filteredRows.slice(start, start + rowsPerPage); + }, [filteredRows, page, rowsPerPage]); + + const handlers = useMemo(() => ({ + handleRunRecording, + handleScheduleRecording, + handleIntegrateRecording, + handleSettingsRecording, + handleEditRobot, + handleDuplicateRobot, + handleDelete: async (id: string) => { + const hasRuns = await checkRunsForRecording(id); + if (hasRuns) { + notify('warning', t('recordingtable.notifications.delete_warning')); + return; + } + + const success = await deleteRecordingFromStorage(id); + if (success) { + setRows([]); + notify('success', t('recordingtable.notifications.delete_success')); + fetchRecordings(); + } + } + }), [handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording, handleEditRobot, handleDuplicateRobot, notify, t]); return ( @@ -200,7 +299,7 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl - {rows.length === 0 ? ( + {isLoading ? ( @@ -210,99 +309,32 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl {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')); - } - }) - - 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} + {visibleRows.map((row) => ( + + ))} )} + Date: Thu, 23 Jan 2025 19:21:53 +0530 Subject: [PATCH 089/174] feat: add debounced search term --- src/components/robot/RecordingsTable.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 4d928289..c679ec14 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -225,8 +225,8 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl // Filter rows based on search term const filteredRows = useMemo(() => { - const searchLower = searchTerm.toLowerCase(); - return searchTerm + const searchLower = debouncedSearchTerm.toLowerCase(); + return debouncedSearchTerm ? rows.filter(row => row.name.toLowerCase().includes(searchLower)) : rows; }, [rows, debouncedSearchTerm]); From 86d0d2c4c366cfa341f1aa8a7e617ff8e54a999f Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 19:50:09 +0530 Subject: [PATCH 090/174] feat: memoize runs table --- src/components/run/RunsTable.tsx | 243 ++++++++++++++++++------------- 1 file changed, 145 insertions(+), 98 deletions(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index 1264dd3c..0bb1edca 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from 'react-i18next'; import Paper from '@mui/material/Paper'; import Table from '@mui/material/Table'; @@ -69,90 +69,149 @@ export const RunsTable: React.FC = ({ const { t } = useTranslation(); const navigate = useNavigate(); - const translatedColumns = columns.map(column => ({ - ...column, - label: t(`runstable.${column.id}`, column.label) - })); + const translatedColumns = useMemo(() => + columns.map(column => ({ + ...column, + label: t(`runstable.${column.id}`, column.label) + })), + [t] + ); const [page, setPage] = useState(0); const [rowsPerPage, setRowsPerPage] = useState(10); const [rows, setRows] = useState([]); const [searchTerm, setSearchTerm] = useState(''); + const [isLoading, setIsLoading] = useState(true); const { notify, rerenderRuns, setRerenderRuns } = useGlobalInfoStore(); - const handleAccordionChange = (robotMetaId: string, isExpanded: boolean) => { - if (isExpanded) { - navigate(`/runs/${robotMetaId}`); - } else { - navigate(`/runs`); - } - }; + const handleAccordionChange = useCallback((robotMetaId: string, isExpanded: boolean) => { + navigate(isExpanded ? `/runs/${robotMetaId}` : '/runs'); + }, [navigate]); - const handleChangePage = (event: unknown, newPage: number) => { + const handleChangePage = useCallback((event: unknown, newPage: number) => { setPage(newPage); - }; + }, []); - const handleChangeRowsPerPage = (event: React.ChangeEvent) => { + const handleChangeRowsPerPage = useCallback((event: React.ChangeEvent) => { setRowsPerPage(+event.target.value); setPage(0); - }; + }, []); - const handleSearchChange = (event: React.ChangeEvent) => { - setSearchTerm(event.target.value); - setPage(0); - }; + const debouncedSearch = useCallback((fn: Function, delay: number) => { + let timeoutId: NodeJS.Timeout; + return (...args: any[]) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => fn(...args), delay); + }; + }, []); - const fetchRuns = async () => { - const runs = await getStoredRuns(); - if (runs) { - const parsedRows: Data[] = runs.map((run: any, index: number) => ({ - id: index, - ...run, - })); - setRows(parsedRows); - } else { - notify('error', t('runstable.notifications.no_runs')); + const handleSearchChange = useCallback((event: React.ChangeEvent) => { + const debouncedSetSearch = debouncedSearch((value: string) => { + setSearchTerm(value); + setPage(0); + }, 300); + debouncedSetSearch(event.target.value); + }, [debouncedSearch]); + + const fetchRuns = useCallback(async () => { + try { + setIsLoading(true); + const runs = await getStoredRuns(); + if (runs) { + const parsedRows: Data[] = runs.map((run: any, index: number) => ({ + id: index, + ...run, + })); + setRows(parsedRows); + } else { + notify('error', t('runstable.notifications.no_runs')); + } + } catch (error) { + notify('error', t('runstable.notifications.fetch_error')); + } finally { + setIsLoading(false); } - }; + }, [notify, t]); useEffect(() => { - if (rows.length === 0 || rerenderRuns) { - fetchRuns(); - setRerenderRuns(false); - } - }, [rerenderRuns, rows.length, setRerenderRuns]); + let mounted = true; - const handleDelete = () => { + if (rows.length === 0 || rerenderRuns) { + fetchRuns().then(() => { + if (mounted) { + setRerenderRuns(false); + } + }); + } + + return () => { + mounted = false; + }; + }, [rerenderRuns, rows.length, setRerenderRuns, fetchRuns]); + + const handleDelete = useCallback(() => { setRows([]); notify('success', t('runstable.notifications.delete_success')); fetchRuns(); - }; + }, [notify, t, fetchRuns]); // Filter rows based on search term - const filteredRows = rows.filter((row) => - row.name.toLowerCase().includes(searchTerm.toLowerCase()) + const filteredRows = useMemo(() => + rows.filter((row) => + row.name.toLowerCase().includes(searchTerm.toLowerCase()) + ), + [rows, searchTerm] ); // Group filtered rows by robot meta id - const groupedRows = filteredRows.reduce((acc, row) => { - if (!acc[row.robotMetaId]) { - acc[row.robotMetaId] = []; - } - acc[row.robotMetaId].push(row); - return acc; - }, {} as Record); + const groupedRows = useMemo(() => + filteredRows.reduce((acc, row) => { + if (!acc[row.robotMetaId]) { + acc[row.robotMetaId] = []; + } + acc[row.robotMetaId].push(row); + return acc; + }, {} as Record), + [filteredRows] + ); + + const renderTableRows = useCallback((data: Data[]) => { + const start = page * rowsPerPage; + const end = start + rowsPerPage; + + return data + .slice(start, end) + .map((row) => ( + + )); + }, [page, rowsPerPage, runId, runningRecordingName, currentInterpretationLog, abortRunHandler, handleDelete]); + + if (isLoading) { + return ( + + + + ); + } return ( - + {t('runstable.runs', 'Runs')} @@ -160,62 +219,50 @@ export const RunsTable: React.FC = ({ sx={{ width: '250px' }} /> - {rows.length === 0 ? ( - - - - ) : ( - - {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)} + TransitionProps={{ unmountOnExit: true }} // Optimize accordion rendering + > + }> + {data[data.length - 1].name} + + + + + + + {translatedColumns.map((column) => ( + + {column.label} + + ))} + + + + {renderTableRows(data)} + +
+
+
+ ))} +
+
); From 7289dadfcb9f2dfdef40e68d27182b0c2bab9d82 Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 20:08:38 +0530 Subject: [PATCH 091/174] feat: incr limit for pagination --- 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 0bb1edca..a83f391f 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -262,7 +262,7 @@ export const RunsTable: React.FC = ({ page={page} onPageChange={handleChangePage} onRowsPerPageChange={handleChangeRowsPerPage} - rowsPerPageOptions={[10, 25, 50]} + rowsPerPageOptions={[10, 25, 50, 100]} />
); From 2abf0f0d7bdd3991168b7c73663b9a338d61e889 Mon Sep 17 00:00:00 2001 From: Rohit Date: Thu, 23 Jan 2025 20:23:53 +0530 Subject: [PATCH 092/174] 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 093/174] 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 094/174] 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 095/174] 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 096/174] 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 097/174] 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 098/174] 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 099/174] 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 100/174] 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 101/174] 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 102/174] 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 103/174] 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 104/174] 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 105/174] 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 106/174] 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 107/174] 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 108/174] 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 109/174] 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 110/174] 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 111/174] 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 112/174] 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 113/174] 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 114/174] 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 115/174] 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 116/174] 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 117/174] 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 118/174] 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 119/174] 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 120/174] 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 121/174] 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 122/174] 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 123/174] 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 124/174] 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 125/174] 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 126/174] 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 127/174] 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 128/174] 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 129/174] 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 130/174] 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 131/174] 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 132/174] 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 133/174] 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 134/174] 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' }} - /> -
: null} - {!row || !row.serializableOutput || !row.binaryOutput + {interpretationInProgress ? ( + + + {t('run_content.loading')} + + ) : (!row || !row.serializableOutput || !row.binaryOutput || (Object.keys(row.serializableOutput).length === 0 && Object.keys(row.binaryOutput).length === 0) - ? {t('run_content.empty_output')} : null} + ? {t('run_content.empty_output')} + : null)} {row.serializableOutput && Object.keys(row.serializableOutput).length !== 0 && From 336d75e1d8dcf1f9904cc2885570732bff9a3566 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sun, 26 Jan 2025 20:57:06 +0530 Subject: [PATCH 144/174] feat: add translation for robot run loader --- public/locales/de.json | 1 + public/locales/en.json | 1 + public/locales/es.json | 1 + public/locales/ja.json | 1 + public/locales/zh.json | 1 + 5 files changed, 5 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 51bbc782..5e6d31bd 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -451,6 +451,7 @@ "log": "Protokoll" }, "empty_output": "Die Ausgabe ist leer.", + "loading": "Ausführung läuft. Extrahierte Daten werden nach Abschluss des Durchlaufs hier angezeigt.", "captured_data": { "title": "Erfasste Daten", "download_json": "Als JSON herunterladen", diff --git a/public/locales/en.json b/public/locales/en.json index a7843bd0..1ce7e920 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -462,6 +462,7 @@ "log": "Log" }, "empty_output": "The output is empty.", + "loading": "Run in progress. Extracted data will appear here once run completes.", "captured_data": { "title": "Captured Data", "download_json": "Download as JSON", diff --git a/public/locales/es.json b/public/locales/es.json index 78e5a9d4..184a9f73 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -452,6 +452,7 @@ "log": "Registro" }, "empty_output": "La salida está vacía.", + "loading": "Ejecución en curso. Los datos extraídos aparecerán aquí una vez que se complete la ejecución.", "captured_data": { "title": "Datos Capturados", "download_json": "Descargar como JSON", diff --git a/public/locales/ja.json b/public/locales/ja.json index fc88abac..313af2e5 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -452,6 +452,7 @@ "log": "ログ" }, "empty_output": "出力は空です。", + "loading": "実行中です。実行が完了すると、抽出されたデータがここに表示されます。", "captured_data": { "title": "キャプチャされたデータ", "download_json": "JSONとしてダウンロード", diff --git a/public/locales/zh.json b/public/locales/zh.json index 1c45464b..57bc7945 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -452,6 +452,7 @@ "log": "日志" }, "empty_output": "输出为空。", + "loading": "运行中。运行完成后,提取的数据将显示在此处。", "captured_data": { "title": "捕获的数据", "download_json": "下载为JSON", From fd17167d53cc6d110dafaf756c553f6f76885f3d Mon Sep 17 00:00:00 2001 From: Rohit Date: Sun, 26 Jan 2025 23:46:24 +0530 Subject: [PATCH 145/174] feat: set run failed on system interruption --- server/src/server.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/server/src/server.ts b/server/src/server.ts index 8c28c2d2..581ecadc 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -18,6 +18,7 @@ import { fork } from 'child_process'; import { capture } from "./utils/analytics"; import swaggerUi from 'swagger-ui-express'; import swaggerSpec from './swagger/config'; +import Run from './models/Run'; const app = express(); app.use(cors({ @@ -113,8 +114,23 @@ server.listen(SERVER_PORT, '0.0.0.0', async () => { } }); -process.on('SIGINT', () => { +process.on('SIGINT', async () => { console.log('Main app shutting down...'); + try { + await Run.update( + { + status: 'failed', + finishedAt: new Date().toLocaleString(), + log: 'Process interrupted during execution - worker shutdown' + }, + { + where: { status: 'running' } + } + ); + } catch (error: any) { + console.error('Error updating runs:', error); + } + if (!isProduction) { workerProcess.kill(); } From 791bd3df5c3c09a6814ff00f0941a8cd7e02de5f Mon Sep 17 00:00:00 2001 From: Rohit Date: Sun, 26 Jan 2025 23:47:10 +0530 Subject: [PATCH 146/174] feat: rm system interruption logic --- server/src/worker.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/server/src/worker.ts b/server/src/worker.ts index 3a82ee73..3010a6b2 100644 --- a/server/src/worker.ts +++ b/server/src/worker.ts @@ -67,9 +67,11 @@ async function jobCounts() { jobCounts(); -process.on('SIGINT', () => { - console.log('Worker shutting down...'); - process.exit(); -}); +// We dont need this right now + +// process.on('SIGINT', () => { +// console.log('Worker shutting down...'); +// process.exit(); +// }); export { workflowQueue, worker }; \ No newline at end of file From b509e40dcebddd5a095b1173fa15501e9fe6b367 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 26 Jan 2025 23:48:21 +0530 Subject: [PATCH 147/174] feat: !show developer mode settings --- src/components/run/RunSettings.tsx | 55 ++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/components/run/RunSettings.tsx b/src/components/run/RunSettings.tsx index a35d2f28..3da0bab8 100644 --- a/src/components/run/RunSettings.tsx +++ b/src/components/run/RunSettings.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState } from "react"; import { GenericModal } from "../ui/GenericModal"; import { MenuItem, TextField, Typography, Switch, FormControlLabel } from "@mui/material"; import { Dropdown } from "../ui/DropdownMui"; @@ -29,24 +29,38 @@ export const RunSettingsModal = ({ isOpen, handleStart, handleClose, isTask, par const [showInterpreterSettings, setShowInterpreterSettings] = useState(false); + const startImmediately = () => { + handleStart(settings); // Start functionality directly + }; + + // Start directly without opening the modal + if (!showInterpreterSettings) { + startImmediately(); + return null; // Do not render the modal + } + return ( -
+
{isTask && ( - Recording parameters: + + Recording parameters: + {params?.map((item, index) => ( setShowInterpreterSettings(!showInterpreterSettings)} />} + control={ + + setShowInterpreterSettings(!showInterpreterSettings) + } + /> + } label="Developer Mode Settings" - sx={{ margin: '20px 0px' }} + sx={{ margin: "20px 0px" }} /> {showInterpreterSettings && ( )} - +
); From 7be0c2accfa2edae1d7895fd1a0bde8dd8aab78e Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 26 Jan 2025 23:51:45 +0530 Subject: [PATCH 148/174] chore: cleanup --- src/components/run/RunSettings.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/run/RunSettings.tsx b/src/components/run/RunSettings.tsx index 3da0bab8..98cd5720 100644 --- a/src/components/run/RunSettings.tsx +++ b/src/components/run/RunSettings.tsx @@ -30,13 +30,12 @@ export const RunSettingsModal = ({ isOpen, handleStart, handleClose, isTask, par const [showInterpreterSettings, setShowInterpreterSettings] = useState(false); const startImmediately = () => { - handleStart(settings); // Start functionality directly + handleStart(settings); }; - // Start directly without opening the modal if (!showInterpreterSettings) { startImmediately(); - return null; // Do not render the modal + return null; } return ( From 9b921cd98758dc63d5ec6355ab196933f6bba6f4 Mon Sep 17 00:00:00 2001 From: Rohit Date: Sun, 26 Jan 2025 23:56:53 +0530 Subject: [PATCH 149/174] feat: add translation for run exist notification --- public/locales/de.json | 2 +- public/locales/en.json | 2 +- public/locales/es.json | 2 +- public/locales/ja.json | 2 +- public/locales/zh.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/locales/de.json b/public/locales/de.json index 51bbc782..9382d353 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -40,7 +40,7 @@ "delete": "Löschen", "duplicate": "Duplizieren", "notifications": { - "delete_warning": "Roboter kann nicht gelöscht werden, da zugehörige Ausführungen vorhanden sind", + "delete_warning": "Der Roboter hat zugehörige Ausführungen. Löschen Sie zuerst die Ausführungen, um den Roboter zu löschen", "delete_success": "Roboter erfolgreich gelöscht", "auth_success": "Roboter erfolgreich authentifiziert" } diff --git a/public/locales/en.json b/public/locales/en.json index a7843bd0..7b575b11 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -41,7 +41,7 @@ "duplicate":"Duplicate", "search":"Search Robots...", "notifications": { - "delete_warning": "Cannot delete robot as it has associated runs", + "delete_warning": "The robot has associated runs. First delete runs to delete the robot", "delete_success": "Robot deleted successfully", "auth_success": "Robot successfully authenticated" } diff --git a/public/locales/es.json b/public/locales/es.json index 78e5a9d4..ee242f89 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -41,7 +41,7 @@ "duplicate": "Duplicar", "search": "Buscar robots...", "notifications": { - "delete_warning": "No se puede eliminar el robot ya que tiene ejecuciones asociadas", + "delete_warning": "El robot tiene ejecuciones asociadas. Primero elimine las ejecuciones para eliminar el robot", "delete_success": "Robot eliminado exitosamente", "auth_success": "Robot autenticado exitosamente" } diff --git a/public/locales/ja.json b/public/locales/ja.json index fc88abac..71d99623 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -41,7 +41,7 @@ "duplicate": "複製", "search": "ロボットを検索...", "notifications": { - "delete_warning": "関連する実行があるため、ロボットを削除できません", + "delete_warning": "ロボットには関連する実行があります。ロボットを削除するには、まず実行を削除してください", "delete_success": "ロボットが正常に削除されました", "auth_success": "ロボットの認証に成功しました" } diff --git a/public/locales/zh.json b/public/locales/zh.json index 1c45464b..82c0efb9 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -41,7 +41,7 @@ "duplicate": "复制", "search": "搜索机器人...", "notifications": { - "delete_warning": "无法删除机器人,因为它有关联的运行记录", + "delete_warning": "该机器人有关联的运行记录。请先删除运行记录才能删除机器人", "delete_success": "机器人删除成功", "auth_success": "机器人认证成功" } From 3af63acbe39b01dedac43bb0cbbb7952e31b8d29 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 26 Jan 2025 23:57:47 +0530 Subject: [PATCH 150/174] feat: avoid re-run during rendering --- src/components/run/RunSettings.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/components/run/RunSettings.tsx b/src/components/run/RunSettings.tsx index 98cd5720..1f40f60e 100644 --- a/src/components/run/RunSettings.tsx +++ b/src/components/run/RunSettings.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import { GenericModal } from "../ui/GenericModal"; import { MenuItem, TextField, Typography, Switch, FormControlLabel } from "@mui/material"; import { Dropdown } from "../ui/DropdownMui"; @@ -29,12 +29,17 @@ export const RunSettingsModal = ({ isOpen, handleStart, handleClose, isTask, par const [showInterpreterSettings, setShowInterpreterSettings] = useState(false); - const startImmediately = () => { - handleStart(settings); - }; + // Run immediately without modal if settings don't need to be shown + useEffect(() => { + if (!showInterpreterSettings) { + handleStart(settings); // Start the run + } + // Ensure this runs only when the component mounts or settings change + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [showInterpreterSettings]); + // Do not render the modal if settings are not shown if (!showInterpreterSettings) { - startImmediately(); return null; } From b961a371b5ee7857360d37ff202de86eecf60e64 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Sun, 26 Jan 2025 23:58:19 +0530 Subject: [PATCH 151/174] fix: format --- src/components/run/RunSettings.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/run/RunSettings.tsx b/src/components/run/RunSettings.tsx index 1f40f60e..caa20e9b 100644 --- a/src/components/run/RunSettings.tsx +++ b/src/components/run/RunSettings.tsx @@ -29,16 +29,13 @@ export const RunSettingsModal = ({ isOpen, handleStart, handleClose, isTask, par const [showInterpreterSettings, setShowInterpreterSettings] = useState(false); - // Run immediately without modal if settings don't need to be shown useEffect(() => { if (!showInterpreterSettings) { - handleStart(settings); // Start the run + handleStart(settings); } - // Ensure this runs only when the component mounts or settings change // eslint-disable-next-line react-hooks/exhaustive-deps }, [showInterpreterSettings]); - // Do not render the modal if settings are not shown if (!showInterpreterSettings) { return null; } From 71d780f765fc539ccb450f9b03789e5b7f878795 Mon Sep 17 00:00:00 2001 From: Rohit Date: Mon, 27 Jan 2025 12:12:40 +0530 Subject: [PATCH 152/174] feat: avoid rerunning the robot --- src/components/run/RunSettings.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/run/RunSettings.tsx b/src/components/run/RunSettings.tsx index caa20e9b..33427d16 100644 --- a/src/components/run/RunSettings.tsx +++ b/src/components/run/RunSettings.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { GenericModal } from "../ui/GenericModal"; import { MenuItem, TextField, Typography, Switch, FormControlLabel } from "@mui/material"; import { Dropdown } from "../ui/DropdownMui"; @@ -28,13 +28,19 @@ export const RunSettingsModal = ({ isOpen, handleStart, handleClose, isTask, par }); const [showInterpreterSettings, setShowInterpreterSettings] = useState(false); + const hasRun = useRef(false); useEffect(() => { - if (!showInterpreterSettings) { + if (!isOpen) { + hasRun.current = false; + return; + } + + if (!showInterpreterSettings && !hasRun.current) { + hasRun.current = true; handleStart(settings); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [showInterpreterSettings]); + }, [isOpen, showInterpreterSettings, settings, handleStart]); if (!showInterpreterSettings) { return null; From bc9d5aaa6ca5a76f36969fdeb029332a97f4418c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:02:28 +0530 Subject: [PATCH 153/174] chore: -rm unused code --- src/App.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index b8497f58..94e4a317 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -93,16 +93,6 @@ function App() { - - // - - // - // - // } /> - // - // - - // ); } From 80d2b50c82c6d4ed37f9b28fe0a6307b58897e42 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:07:34 +0530 Subject: [PATCH 154/174] chore(ui): cleanup old theme --- src/App.tsx | 78 ----------------------------------------------------- 1 file changed, 78 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 94e4a317..bdf87a88 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,84 +6,6 @@ import { PageWrapper } from "./pages/PageWrapper"; import i18n from "./i18n"; import ThemeModeProvider from './context/theme-provider'; - -const theme = createTheme({ - palette: { - primary: { - main: "#ff00c3", - contrastText: "#ffffff", - }, - }, - components: { - MuiButton: { - styleOverrides: { - root: { - // Default styles for all buttons (optional) - textTransform: "none", - }, - containedPrimary: { - // Styles for 'contained' variant with 'primary' color - "&:hover": { - backgroundColor: "#ff66d9", - }, - }, - outlined: { - // Apply white background for all 'outlined' variant buttons - backgroundColor: "#ffffff", - "&:hover": { - backgroundColor: "#f0f0f0", // Optional lighter background on hover - }, - }, - }, - }, - MuiLink: { - styleOverrides: { - root: { - "&:hover": { - color: "#ff00c3", - }, - }, - }, - }, - MuiIconButton: { - styleOverrides: { - root: { - // '&:hover': { - // color: "#ff66d9", - // }, - }, - }, - }, - MuiTab: { - styleOverrides: { - root: { - textTransform: "none", - }, - }, - }, - MuiAlert: { - styleOverrides: { - standardInfo: { - backgroundColor: "#fce1f4", - color: "#ff00c3", - "& .MuiAlert-icon": { - color: "#ff00c3", - }, - }, - }, - }, - MuiAlertTitle: { - styleOverrides: { - root: { - "& .MuiAlert-icon": { - color: "#ffffff", - }, - }, - }, - }, - }, -}); - function App() { return ( From 89f653db09eefdf2334d6ab6fb5ad9902421755a Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:09:17 +0530 Subject: [PATCH 155/174] chore: -rm ThemeProvider imports --- src/App.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index bdf87a88..13d04f83 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,5 @@ 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/PageWrapper"; import i18n from "./i18n"; From fd45a334794ff36543974762ea79e03f04d10981 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:13:12 +0530 Subject: [PATCH 156/174] fix: format --- src/context/theme-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/context/theme-provider.tsx b/src/context/theme-provider.tsx index d53ced24..fe773ff9 100644 --- a/src/context/theme-provider.tsx +++ b/src/context/theme-provider.tsx @@ -218,7 +218,7 @@ const darkTheme = createTheme({ }); const ThemeModeContext = createContext({ - toggleTheme: () => {}, + toggleTheme: () => { }, darkMode: false, }); From e8347d73a25d5e29a79e195974e1f9a216aae0a8 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:23:52 +0530 Subject: [PATCH 157/174] feat: add error to paletter --- src/context/theme-provider.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/context/theme-provider.tsx b/src/context/theme-provider.tsx index fe773ff9..71bfb3b3 100644 --- a/src/context/theme-provider.tsx +++ b/src/context/theme-provider.tsx @@ -86,6 +86,12 @@ const darkTheme = createTheme({ main: "#ff00c3", contrastText: "#ffffff", }, + error: { + main: '#f44336', + light: '#e57373', + dark: '#d32f2f', + contrastText: '#ffffff', + }, background: { default: '#121212', paper: '#1e1e1e', From bafd6948a97fe7cdfffad05c51d578eaa4d9e250 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:30:37 +0530 Subject: [PATCH 158/174] feat: outlined error palette --- src/context/theme-provider.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/context/theme-provider.tsx b/src/context/theme-provider.tsx index 71bfb3b3..5624f2af 100644 --- a/src/context/theme-provider.tsx +++ b/src/context/theme-provider.tsx @@ -130,6 +130,14 @@ const darkTheme = createTheme({ backgroundColor: 'rgba(255, 0, 195, 0.08)', borderColor: '#ff66d9', }, + '&.MuiButton-outlinedError': { + borderColor: '#f44336', + color: '#f44336', + "&:hover": { + backgroundColor: 'rgba(244, 67, 54, 0.08)', + borderColor: '#d32f2f', + }, + }, }, }, }, From 06f631df071818be49b906171443ef7b77af1cc6 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:34:19 +0530 Subject: [PATCH 159/174] feat: icon outlined error palette --- src/context/theme-provider.tsx | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/context/theme-provider.tsx b/src/context/theme-provider.tsx index 5624f2af..4be51ed6 100644 --- a/src/context/theme-provider.tsx +++ b/src/context/theme-provider.tsx @@ -153,12 +153,18 @@ const darkTheme = createTheme({ }, MuiIconButton: { styleOverrides: { - root: { - color: '#ffffff', - "&:hover": { - backgroundColor: 'rgba(255, 0, 195, 0.08)', - }, + root: { + color: '#ffffff', + "&:hover": { + backgroundColor: 'rgba(255, 0, 195, 0.08)', }, + '&.MuiIconButton-colorError': { + color: '#f44336', + "&:hover": { + backgroundColor: 'rgba(244, 67, 54, 0.08)', + }, + }, + }, }, }, MuiTab: { From ecdcde384b387ee7c324aadd2785ab221d2cc6be Mon Sep 17 00:00:00 2001 From: amhsirak Date: Mon, 27 Jan 2025 22:34:33 +0530 Subject: [PATCH 160/174] chore: lint --- src/context/theme-provider.tsx | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/context/theme-provider.tsx b/src/context/theme-provider.tsx index 4be51ed6..75dd4b8b 100644 --- a/src/context/theme-provider.tsx +++ b/src/context/theme-provider.tsx @@ -153,18 +153,18 @@ const darkTheme = createTheme({ }, MuiIconButton: { styleOverrides: { - root: { - color: '#ffffff', - "&:hover": { - backgroundColor: 'rgba(255, 0, 195, 0.08)', + root: { + color: '#ffffff', + "&:hover": { + backgroundColor: 'rgba(255, 0, 195, 0.08)', + }, + '&.MuiIconButton-colorError': { + color: '#f44336', + "&:hover": { + backgroundColor: 'rgba(244, 67, 54, 0.08)', + }, + }, }, - '&.MuiIconButton-colorError': { - color: '#f44336', - "&:hover": { - backgroundColor: 'rgba(244, 67, 54, 0.08)', - }, - }, - }, }, }, MuiTab: { From 55ddd5db5cae6522b267449982a26d6727c0aef8 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 28 Jan 2025 00:46:04 +0530 Subject: [PATCH 161/174] feat: sort func for runs table --- src/components/run/RunsTable.tsx | 137 +++++++++++++++++++++++++++---- 1 file changed, 122 insertions(+), 15 deletions(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index a83f391f..82acf89b 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, CircularProgress } from '@mui/material'; +import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField, CircularProgress, Tooltip } from '@mui/material'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import SearchIcon from '@mui/icons-material/Search'; import { useNavigate } from 'react-router-dom'; @@ -17,6 +17,7 @@ import { useGlobalInfoStore } from "../../context/globalInfo"; import { getStoredRuns } from "../../api/storage"; import { RunSettings } from "./RunSettings"; import { CollapsibleRow } from "./ColapsibleRow"; +import { ArrowDownward, ArrowUpward, UnfoldMore } from '@mui/icons-material'; export const columns: readonly Column[] = [ { id: 'runStatus', label: 'Status', minWidth: 80 }, @@ -27,6 +28,15 @@ export const columns: readonly Column[] = [ { id: 'delete', label: 'Delete', minWidth: 80 }, ]; +type SortDirection = 'asc' | 'desc' | 'none'; + +interface AccordionSortConfig { + [robotMetaId: string]: { + field: keyof Data | null; + direction: SortDirection; + }; +} + interface Column { id: 'runStatus' | 'name' | 'startedAt' | 'finishedAt' | 'delete' | 'settings'; label: string; @@ -69,6 +79,26 @@ export const RunsTable: React.FC = ({ const { t } = useTranslation(); const navigate = useNavigate(); + const [accordionSortConfigs, setAccordionSortConfigs] = useState({}); + + const handleSort = useCallback((columnId: keyof Data, robotMetaId: string) => { + setAccordionSortConfigs(prevConfigs => { + const currentConfig = prevConfigs[robotMetaId] || { field: null, direction: 'none' }; + const newDirection: SortDirection = + currentConfig.field !== columnId ? 'asc' : + currentConfig.direction === 'none' ? 'asc' : + currentConfig.direction === 'asc' ? 'desc' : 'none'; + + return { + ...prevConfigs, + [robotMetaId]: { + field: newDirection === 'none' ? null : columnId, + direction: newDirection, + } + }; + }); + }, []); + const translatedColumns = useMemo(() => columns.map(column => ({ ...column, @@ -157,12 +187,12 @@ export const RunsTable: React.FC = ({ }, [notify, t, fetchRuns]); // Filter rows based on search term - const filteredRows = useMemo(() => - rows.filter((row) => + const filteredRows = useMemo(() => { + let result = rows.filter((row) => row.name.toLowerCase().includes(searchTerm.toLowerCase()) - ), - [rows, searchTerm] - ); + ); + return result; + }, [rows, searchTerm]); // Group filtered rows by robot meta id const groupedRows = useMemo(() => @@ -176,11 +206,27 @@ export const RunsTable: React.FC = ({ [filteredRows] ); - const renderTableRows = useCallback((data: Data[]) => { + const renderTableRows = useCallback((data: Data[], robotMetaId: string) => { const start = page * rowsPerPage; const end = start + rowsPerPage; + + let sortedData = [...data]; + const sortConfig = accordionSortConfigs[robotMetaId]; - return data + if (sortConfig?.field === 'startedAt' || sortConfig?.field === 'finishedAt') { + if (sortConfig.direction !== 'none') { + sortedData.sort((a, b) => { + const dateA = new Date(a[sortConfig.field!].replace(/(\d+)\/(\d+)\//, '$2/$1/')); + const dateB = new Date(b[sortConfig.field!].replace(/(\d+)\/(\d+)\//, '$2/$1/')); + + return sortConfig.direction === 'asc' + ? dateA.getTime() - dateB.getTime() + : dateB.getTime() - dateA.getTime(); + }); + } + } + + return sortedData .slice(start, end) .map((row) => ( = ({ runningRecordingName={runningRecordingName} /> )); - }, [page, rowsPerPage, runId, runningRecordingName, currentInterpretationLog, abortRunHandler, handleDelete]); + }, [page, rowsPerPage, runId, runningRecordingName, currentInterpretationLog, abortRunHandler, handleDelete, accordionSortConfigs]); + + const renderSortIcon = useCallback((column: Column, robotMetaId: string) => { + const sortConfig = accordionSortConfigs[robotMetaId]; + if (column.id !== 'startedAt' && column.id !== 'finishedAt') return null; + + if (sortConfig?.field !== column.id) { + return ( + + ); + } + + return sortConfig.direction === 'asc' + ? + : sortConfig.direction === 'desc' + ? + : ; + }, [accordionSortConfigs]); if (isLoading) { return ( @@ -221,10 +293,10 @@ export const RunsTable: React.FC = ({ - {Object.entries(groupedRows).map(([id, data]) => ( + {Object.entries(groupedRows).map(([robotMetaId, data]) => ( handleAccordionChange(id, isExpanded)} + key={robotMetaId} + onChange={(event, isExpanded) => handleAccordionChange(robotMetaId, isExpanded)} TransitionProps={{ unmountOnExit: true }} // Optimize accordion rendering > }> @@ -239,15 +311,50 @@ export const RunsTable: React.FC = ({ { + if (column.id === 'startedAt' || column.id === 'finishedAt') { + handleSort(column.id, robotMetaId); + } + }} > - {column.label} + + + {column.label} + + {renderSortIcon(column, robotMetaId)} + + + ))} - {renderTableRows(data)} + {renderTableRows(data, robotMetaId)} From 2d93465a758221df9e93043c4f687c23d1121268 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 28 Jan 2025 00:49:08 +0530 Subject: [PATCH 162/174] feat: rm fallback tooltip --- 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 82acf89b..8151186d 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -324,7 +324,7 @@ export const RunsTable: React.FC = ({ From f8fcc856d769c44cca0079b2b202ce60ac42acda Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 28 Jan 2025 00:49:36 +0530 Subject: [PATCH 163/174] feat: add translation for runstable tooltip --- public/locales/de.json | 1 + public/locales/en.json | 1 + public/locales/es.json | 1 + public/locales/ja.json | 1 + public/locales/zh.json | 1 + 5 files changed, 5 insertions(+) diff --git a/public/locales/de.json b/public/locales/de.json index 5c3139f7..613ddfef 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -62,6 +62,7 @@ "delete": "Löschen", "settings": "Einstellungen", "search": "Ausführungen suchen...", + "sort_tooltip": "Zum Sortieren klicken", "notifications": { "no_runs": "Keine Ausführungen gefunden. Bitte versuchen Sie es erneut.", "delete_success": "Ausführung erfolgreich gelöscht" diff --git a/public/locales/en.json b/public/locales/en.json index c0cd154c..85bd3148 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -63,6 +63,7 @@ "delete":"Delete", "settings":"Settings", "search":"Search Runs...", + "sort_tooltip": "Click to sort", "notifications": { "no_runs": "No runs found. Please try again.", "delete_success": "Run deleted successfully" diff --git a/public/locales/es.json b/public/locales/es.json index ae61ea14..46bded05 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -63,6 +63,7 @@ "delete": "Eliminar", "settings": "Ajustes", "search": "Buscar ejecuciones...", + "sort_tooltip": "Haga clic para ordenar", "notifications": { "no_runs": "No se encontraron ejecuciones. Por favor, inténtelo de nuevo.", "delete_success": "Ejecución eliminada con éxito" diff --git a/public/locales/ja.json b/public/locales/ja.json index 1ffa1757..ad78c8f5 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -63,6 +63,7 @@ "delete": "削除", "settings": "設定", "search": "実行を検索...", + "sort_tooltip": "クリックして並べ替え", "notifications": { "no_runs": "実行が見つかりません。もう一度お試しください。", "delete_success": "実行が正常に削除されました" diff --git a/public/locales/zh.json b/public/locales/zh.json index 7bd985d2..cd1a4f9f 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -63,6 +63,7 @@ "delete": "删除", "settings": "设置", "search": "搜索运行记录...", + "sort_tooltip": "点击排序", "notifications": { "no_runs": "未找到运行记录。请重试。", "delete_success": "运行记录删除成功" From 48cbedc40c3337a3afc4a0ce88f09db7c0586230 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 28 Jan 2025 11:53:47 +0530 Subject: [PATCH 164/174] feat: better datetime parsing --- src/components/run/RunsTable.tsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index 8151186d..92233214 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -206,6 +206,18 @@ export const RunsTable: React.FC = ({ [filteredRows] ); + const parseDateString = (dateStr: string): Date => { + try { + if (dateStr.includes('PM') || dateStr.includes('AM')) { + return new Date(dateStr); + } + + return new Date(dateStr.replace(/(\d+)\/(\d+)\//, '$2/$1/')) + } catch { + return new Date(0); + } + }; + const renderTableRows = useCallback((data: Data[], robotMetaId: string) => { const start = page * rowsPerPage; const end = start + rowsPerPage; @@ -216,8 +228,8 @@ export const RunsTable: React.FC = ({ if (sortConfig?.field === 'startedAt' || sortConfig?.field === 'finishedAt') { if (sortConfig.direction !== 'none') { sortedData.sort((a, b) => { - const dateA = new Date(a[sortConfig.field!].replace(/(\d+)\/(\d+)\//, '$2/$1/')); - const dateB = new Date(b[sortConfig.field!].replace(/(\d+)\/(\d+)\//, '$2/$1/')); + const dateA = parseDateString(a[sortConfig.field!]); + const dateB = parseDateString(b[sortConfig.field!]); return sortConfig.direction === 'asc' ? dateA.getTime() - dateB.getTime() From f78764bfa686c81d1d8e9986bcbb7dc7b0897d1e Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 28 Jan 2025 22:07:43 +0530 Subject: [PATCH 165/174] feat: remove project name from upgrade button --- 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 31eed9f1..5e54b44b 100644 --- a/src/components/dashboard/NavBar.tsx +++ b/src/components/dashboard/NavBar.tsx @@ -200,7 +200,7 @@ export const NavBar: React.FC = ({ border: "#00000099 1px solid", '&:hover': { color: '#ff00c3', border: '#ff00c3 1px solid' } }}> - {t('navbar.upgrade.button')} Maxun + {t('navbar.upgrade.button')} Date: Tue, 28 Jan 2025 22:10:08 +0530 Subject: [PATCH 166/174] chore: format imports --- src/components/dashboard/NavBar.tsx | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/components/dashboard/NavBar.tsx b/src/components/dashboard/NavBar.tsx index 5e54b44b..ec5fcf7c 100644 --- a/src/components/dashboard/NavBar.tsx +++ b/src/components/dashboard/NavBar.tsx @@ -4,8 +4,33 @@ import axios from 'axios'; 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, Description, LightMode, DarkMode } from "@mui/icons-material"; +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, + Description, + LightMode, + DarkMode +} from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../../context/auth'; import { SaveRecording } from '../recorder/SaveRecording'; From e74ceae97b787008a37697cb1e36ab0938cc260c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:13:11 +0530 Subject: [PATCH 167/174] feat: use Request instead of AuthenticatedRequest --- server/src/routes/proxy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/routes/proxy.ts b/server/src/routes/proxy.ts index d68a889e..22b3465d 100644 --- a/server/src/routes/proxy.ts +++ b/server/src/routes/proxy.ts @@ -12,7 +12,7 @@ interface AuthenticatedRequest extends Request { user?: { id: string }; } -router.post('/config', requireSignIn, async (req: AuthenticatedRequest, res: Response) => { +router.post('/config', requireSignIn, async (req: Request, res: Response) => { const { server_url, username, password } = req.body; try { @@ -57,7 +57,7 @@ router.post('/config', requireSignIn, async (req: AuthenticatedRequest, res: Res } }); -router.get('/test', requireSignIn, async (req: AuthenticatedRequest, res: Response) => { +router.get('/test', requireSignIn, async (req: Request, res: Response) => { try { if (!req.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); @@ -98,7 +98,7 @@ router.get('/test', requireSignIn, async (req: AuthenticatedRequest, res: Respon } }); -router.get('/config', requireSignIn, async (req: AuthenticatedRequest, res: Response) => { +router.get('/config', requireSignIn, async (req: Request, res: Response) => { try { if (!req.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); @@ -125,7 +125,7 @@ router.get('/config', requireSignIn, async (req: AuthenticatedRequest, res: Resp } }); -router.delete('/config', requireSignIn, async (req: AuthenticatedRequest, res: Response) => { +router.delete('/config', requireSignIn, async (req: Request, res: Response) => { if (!req.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } From de241e141e9550ba7f17bf056f5763cabe56f2a1 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:14:20 +0530 Subject: [PATCH 168/174] feat: create authenticatedReq --- server/src/routes/proxy.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/routes/proxy.ts b/server/src/routes/proxy.ts index 22b3465d..efd05421 100644 --- a/server/src/routes/proxy.ts +++ b/server/src/routes/proxy.ts @@ -14,6 +14,7 @@ interface AuthenticatedRequest extends Request { router.post('/config', requireSignIn, async (req: Request, res: Response) => { const { server_url, username, password } = req.body; + const authenticatedReq = req as AuthenticatedRequest; try { @@ -58,6 +59,7 @@ router.post('/config', requireSignIn, async (req: Request, res: Response) => { }); router.get('/test', requireSignIn, async (req: Request, res: Response) => { + const authenticatedReq = req as AuthenticatedRequest; try { if (!req.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); @@ -99,6 +101,7 @@ router.get('/test', requireSignIn, async (req: Request, res: Response) => { }); router.get('/config', requireSignIn, async (req: Request, res: Response) => { + const authenticatedReq = req as AuthenticatedRequest; try { if (!req.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); @@ -126,6 +129,7 @@ router.get('/config', requireSignIn, async (req: Request, res: Response) => { }); router.delete('/config', requireSignIn, async (req: Request, res: Response) => { + const authenticatedReq = req as AuthenticatedRequest; if (!req.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } From 2077e2a89fd0a807ced530f3ed0214d68d1d8c43 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:15:10 +0530 Subject: [PATCH 169/174] feat: use authenticatedReq instead of req --- server/src/routes/proxy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/routes/proxy.ts b/server/src/routes/proxy.ts index efd05421..ccf7e959 100644 --- a/server/src/routes/proxy.ts +++ b/server/src/routes/proxy.ts @@ -18,7 +18,7 @@ router.post('/config', requireSignIn, async (req: Request, res: Response) => { try { - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } @@ -61,7 +61,7 @@ router.post('/config', requireSignIn, async (req: Request, res: Response) => { router.get('/test', requireSignIn, async (req: Request, res: Response) => { const authenticatedReq = req as AuthenticatedRequest; try { - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } @@ -103,7 +103,7 @@ router.get('/test', requireSignIn, async (req: Request, res: Response) => { router.get('/config', requireSignIn, async (req: Request, res: Response) => { const authenticatedReq = req as AuthenticatedRequest; try { - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } @@ -130,7 +130,7 @@ router.get('/config', requireSignIn, async (req: Request, res: Response) => { router.delete('/config', requireSignIn, async (req: Request, res: Response) => { const authenticatedReq = req as AuthenticatedRequest; - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } From b95e8d18efccf97164ef1eb98f2e7b0e95a0adc2 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:15:53 +0530 Subject: [PATCH 170/174] feat: use authenticatedReq to query db --- server/src/routes/proxy.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/routes/proxy.ts b/server/src/routes/proxy.ts index ccf7e959..f481cc45 100644 --- a/server/src/routes/proxy.ts +++ b/server/src/routes/proxy.ts @@ -22,7 +22,7 @@ router.post('/config', requireSignIn, async (req: Request, res: Response) => { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } - const user = await User.findByPk(req.user.id, { + const user = await User.findByPk(authenticatedReq.user.id, { attributes: { exclude: ['password'] }, }); @@ -65,7 +65,7 @@ router.get('/test', requireSignIn, async (req: Request, res: Response) => { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } - const user = await User.findByPk(req.user.id, { + const user = await User.findByPk(authenticatedReq.user.id, { attributes: ['proxy_url', 'proxy_username', 'proxy_password'], raw: true }); @@ -107,7 +107,7 @@ router.get('/config', requireSignIn, async (req: Request, res: Response) => { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } - const user = await User.findByPk(req.user.id, { + const user = await User.findByPk(authenticatedReq.user.id, { attributes: ['proxy_url', 'proxy_username', 'proxy_password'], raw: true, }); @@ -134,7 +134,7 @@ router.delete('/config', requireSignIn, async (req: Request, res: Response) => { return res.status(401).json({ ok: false, error: 'Unauthorized' }); } - const user = await User.findByPk(req.user.id); + const user = await User.findByPk(authenticatedReq.user.id); if (!user) { return res.status(404).json({ message: 'User not found' }); From bb77fe3b9313f44727275193a46ae90e45e92643 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:17:35 +0530 Subject: [PATCH 171/174] feat: use Request instead of AuthenticatedRequest --- server/src/routes/auth.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 49af7090..f76c7758 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -107,7 +107,7 @@ router.get("/logout", async (req, res) => { router.get( "/current-user", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { try { if (!req.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); @@ -135,7 +135,7 @@ router.get( router.get( "/user/:id", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { try { const { id } = req.params; if (!id) { @@ -164,7 +164,7 @@ router.get( router.post( "/generate-api-key", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { try { if (!req.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); @@ -204,7 +204,7 @@ router.post( router.get( "/api-key", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { try { if (!req.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); @@ -232,7 +232,7 @@ router.get( router.delete( "/delete-api-key", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { if (!req.user) { return res.status(401).send({ error: "Unauthorized" }); } @@ -294,7 +294,7 @@ router.get("/google", (req, res) => { router.get( "/google/callback", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { const { code, state } = req.query; try { if (!state) { @@ -403,7 +403,7 @@ router.get( router.post( "/gsheets/data", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { const { spreadsheetId, robotId } = req.body; if (!req.user) { return res.status(401).send({ error: "Unauthorized" }); @@ -520,7 +520,7 @@ router.post("/gsheets/update", requireSignIn, async (req, res) => { router.post( "/gsheets/remove", requireSignIn, - async (req: AuthenticatedRequest, res) => { + async (req: Request, res) => { const { robotId } = req.body; if (!robotId) { return res.status(400).json({ message: "Robot ID is required" }); From 7ae17685c5a54730abf0440476797fd3ba04958b Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:22:15 +0530 Subject: [PATCH 172/174] feat: create authenticatedReq --- server/src/routes/auth.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index f76c7758..58c6b6af 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -108,6 +108,7 @@ router.get( "/current-user", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; try { if (!req.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); @@ -165,6 +166,7 @@ router.post( "/generate-api-key", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; try { if (!req.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); @@ -205,6 +207,7 @@ router.get( "/api-key", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; try { if (!req.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); @@ -233,6 +236,7 @@ router.delete( "/delete-api-key", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; if (!req.user) { return res.status(401).send({ error: "Unauthorized" }); } @@ -295,6 +299,7 @@ router.get( "/google/callback", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; const { code, state } = req.query; try { if (!state) { @@ -404,6 +409,7 @@ router.post( "/gsheets/data", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; const { spreadsheetId, robotId } = req.body; if (!req.user) { return res.status(401).send({ error: "Unauthorized" }); @@ -521,6 +527,7 @@ router.post( "/gsheets/remove", requireSignIn, async (req: Request, res) => { + const authenticatedReq = req as AuthenticatedRequest; const { robotId } = req.body; if (!robotId) { return res.status(400).json({ message: "Robot ID is required" }); From 6d99f01e2d8e8d549e836da854dcfe10ca678b0c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:23:21 +0530 Subject: [PATCH 173/174] feat: use authenticatedReq instead of req --- server/src/routes/auth.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 58c6b6af..7802427e 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -110,7 +110,7 @@ router.get( async (req: Request, res) => { const authenticatedReq = req as AuthenticatedRequest; try { - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); } const user = await User.findByPk(req.user.id, { @@ -168,7 +168,7 @@ router.post( async (req: Request, res) => { const authenticatedReq = req as AuthenticatedRequest; try { - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); } const user = await User.findByPk(req.user.id, { @@ -209,7 +209,7 @@ router.get( async (req: Request, res) => { const authenticatedReq = req as AuthenticatedRequest; try { - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); } @@ -237,7 +237,7 @@ router.delete( requireSignIn, async (req: Request, res) => { const authenticatedReq = req as AuthenticatedRequest; - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).send({ error: "Unauthorized" }); } @@ -325,7 +325,7 @@ router.get( return res.status(400).json({ message: "Email not found" }); } - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).send({ error: "Unauthorized" }); } @@ -411,7 +411,7 @@ router.post( async (req: Request, res) => { const authenticatedReq = req as AuthenticatedRequest; const { spreadsheetId, robotId } = req.body; - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).send({ error: "Unauthorized" }); } const user = await User.findByPk(req.user.id, { raw: true }); @@ -533,7 +533,7 @@ router.post( return res.status(400).json({ message: "Robot ID is required" }); } - if (!req.user) { + if (!authenticatedReq.user) { return res.status(401).send({ error: "Unauthorized" }); } From e335e138ab55a91e17b2cf9d73b3b566a5be0aea Mon Sep 17 00:00:00 2001 From: amhsirak Date: Wed, 29 Jan 2025 15:24:19 +0530 Subject: [PATCH 174/174] feat: use authenticatedReq to query db --- server/src/routes/auth.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/src/routes/auth.ts b/server/src/routes/auth.ts index 7802427e..e7ee62d9 100644 --- a/server/src/routes/auth.ts +++ b/server/src/routes/auth.ts @@ -113,7 +113,7 @@ router.get( if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); } - const user = await User.findByPk(req.user.id, { + const user = await User.findByPk(authenticatedReq.user.id, { attributes: { exclude: ["password"] }, }); if (!user) { @@ -171,7 +171,7 @@ router.post( if (!authenticatedReq.user) { return res.status(401).json({ ok: false, error: "Unauthorized" }); } - const user = await User.findByPk(req.user.id, { + const user = await User.findByPk(authenticatedReq.user.id, { attributes: { exclude: ["password"] }, }); @@ -213,7 +213,7 @@ router.get( return res.status(401).json({ ok: false, error: "Unauthorized" }); } - const user = await User.findByPk(req.user.id, { + const user = await User.findByPk(authenticatedReq.user.id, { raw: true, attributes: ["api_key"], }); @@ -242,7 +242,7 @@ router.delete( } try { - const user = await User.findByPk(req.user.id, { raw: true }); + const user = await User.findByPk(authenticatedReq.user.id, { raw: true }); if (!user) { return res.status(404).json({ message: "User not found" }); @@ -252,7 +252,7 @@ router.delete( return res.status(404).json({ message: "API Key not found" }); } - await User.update({ api_key: null }, { where: { id: req.user.id } }); + await User.update({ api_key: null }, { where: { id: authenticatedReq.user.id } }); capture("maxun-oss-api-key-deleted", { user_id: user.id, @@ -330,7 +330,7 @@ router.get( } // Get the currently authenticated user (from `requireSignIn`) - let user = await User.findOne({ where: { id: req.user.id } }); + let user = await User.findOne({ where: { id: authenticatedReq.user.id } }); if (!user) { return res.status(400).json({ message: "User not found" }); @@ -414,7 +414,7 @@ router.post( if (!authenticatedReq.user) { return res.status(401).send({ error: "Unauthorized" }); } - const user = await User.findByPk(req.user.id, { raw: true }); + const user = await User.findByPk(authenticatedReq.user.id, { raw: true }); if (!user) { return res.status(400).json({ message: "User not found" }); @@ -555,7 +555,7 @@ router.post( }); capture("maxun-oss-google-sheet-integration-removed", { - user_id: req.user.id, + user_id: authenticatedReq.user.id, robot_id: robotId, deleted_at: new Date().toISOString(), });