From d2dbef74fb39894b3b9565dfeb9789f44e0c564c Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:26:17 +0530 Subject: [PATCH 01/11] feat: get target url from req body --- server/src/routes/storage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 357c199f..31cf455a 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -259,7 +259,7 @@ function handleWorkflowActions(workflow: any[], credentials: Credentials) { router.put('/recordings/:id', requireSignIn, async (req: AuthenticatedRequest, res) => { try { const { id } = req.params; - const { name, limit, credentials } = req.body; + const { name, limit, credentials, targetUrl } = req.body; // Validate input if (!name && limit === undefined) { From 0b1621fa4abd3171dd842b06767d1ea36068ed24 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:27:24 +0530 Subject: [PATCH 02/11] feat: validate target_url --- server/src/routes/storage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 31cf455a..1717cdff 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -262,8 +262,8 @@ router.put('/recordings/:id', requireSignIn, async (req: AuthenticatedRequest, r const { name, limit, credentials, targetUrl } = req.body; // Validate input - if (!name && limit === undefined) { - return res.status(400).json({ error: 'Either "name" or "limit" must be provided.' }); + if (!name && limit === undefined && !targetUrl) { + return res.status(400).json({ error: 'Either "name", "limit" or "target_url" must be provided.' }); } // Fetch the robot by ID From 2114c462b8e1c8a2400fafde05962a0ea257b2da Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:44:02 +0530 Subject: [PATCH 03/11] feat: edit target url in the workflow --- server/src/routes/storage.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/server/src/routes/storage.ts b/server/src/routes/storage.ts index 1717cdff..af7850f0 100644 --- a/server/src/routes/storage.ts +++ b/server/src/routes/storage.ts @@ -278,6 +278,27 @@ router.put('/recordings/:id', requireSignIn, async (req: AuthenticatedRequest, r robot.set('recording_meta', { ...robot.recording_meta, name }); } + if (targetUrl) { + const updatedWorkflow = robot.recording.workflow.map((step) => { + if (step.where?.url && step.where.url !== "about:blank") { + step.where.url = targetUrl; + } + + step.what.forEach((action) => { + if (action.action === "goto" && action.args?.length) { + action.args[0] = targetUrl; + } + }); + + return step; + }); + + robot.set('recording', { ...robot.recording, workflow: updatedWorkflow }); + robot.changed('recording', true); + } + + await robot.save(); + let workflow = [...robot.recording.workflow]; // Create a copy of the workflow if (credentials) { From 5453648d2a209b0cca24248d218f3a39b66b0bf2 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:44:25 +0530 Subject: [PATCH 04/11] feat: pass targetUrl --- src/api/storage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/storage.ts b/src/api/storage.ts index 0bfcaf15..e3359563 100644 --- a/src/api/storage.ts +++ b/src/api/storage.ts @@ -28,7 +28,7 @@ export const getStoredRecordings = async (): Promise => { } }; -export const updateRecording = async (id: string, data: { name?: string; limit?: number, credentials?: Credentials }): Promise => { +export const updateRecording = async (id: string, data: { name?: string; limit?: number, credentials?: Credentials, targetUrl?: string }): Promise => { try { const response = await axios.put(`${apiUrl}/storage/recordings/${id}`, data); if (response.status === 200) { From ca9f63b09f684ef671a61767c90875c1879df4d5 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:44:58 +0530 Subject: [PATCH 05/11] feat: handle target url change --- src/components/robot/RobotEdit.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 9c1a0cf6..f7e5fdfe 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -306,6 +306,24 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin }); }; + const handleTargetUrlChange = (newUrl: string) => { + setRobot((prev) => { + if (!prev) return prev; + + const updatedWorkflow = [...prev.recording.workflow]; + const lastPairIndex = updatedWorkflow.length - 1; + + if (lastPairIndex >= 0) { + const gotoAction = updatedWorkflow[lastPairIndex]?.what?.find(action => action.action === "goto"); + if (gotoAction && gotoAction.args && gotoAction.args.length > 0) { + gotoAction.args[0] = newUrl; + } + } + + return { ...prev, recording: { ...prev.recording, workflow: updatedWorkflow } }; + }); + }; + const renderAllCredentialFields = () => { return ( <> From 8165e385cf4ee06946e37ff74fad1e27b04f9939 Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:45:21 +0530 Subject: [PATCH 06/11] feat: get last pair & target url --- 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 f7e5fdfe..e56d9cf8 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -408,6 +408,9 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return acc; }, {} as Record); + const lastPair = robot.recording.workflow[robot.recording.workflow.length - 1]; + const targetUrl = lastPair?.what.find(action => action.action === "goto")?.args?.[0]; + const payload = { name: robot.recording_meta.name, limit: robot.recording.workflow[0]?.what[0]?.args?.[0]?.limit, From 8b9f402db96788575575b99470be0c3b9adf5bad Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:45:41 +0530 Subject: [PATCH 07/11] feat: pass target url in payload --- 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 e56d9cf8..264c522c 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -408,13 +408,14 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin return acc; }, {} as Record); - const lastPair = robot.recording.workflow[robot.recording.workflow.length - 1]; + const lastPair = robot.recording.workflow[robot.recording.workflow.length - 1]; const targetUrl = lastPair?.what.find(action => action.action === "goto")?.args?.[0]; const payload = { name: robot.recording_meta.name, limit: robot.recording.workflow[0]?.what[0]?.args?.[0]?.limit, credentials: credentialsForPayload, + targetUrl: targetUrl, }; const success = await updateRecording(robot.recording_meta.id, payload); From 150b77fe5a200baf8b5bb300b06f7e7f7df8f4df Mon Sep 17 00:00:00 2001 From: amhsirak Date: Tue, 18 Mar 2025 23:45:51 +0530 Subject: [PATCH 08/11] feat: get last pair & target url --- 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 264c522c..8ac465d5 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -435,6 +435,9 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin } }; + const lastPair = robot?.recording.workflow[robot?.recording.workflow.length - 1]; + const targetUrl = lastPair?.what.find(action => action.action === "goto")?.args?.[0]; + return ( Date: Tue, 18 Mar 2025 23:46:12 +0530 Subject: [PATCH 09/11] feat: text field for url edit --- src/components/robot/RobotEdit.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 8ac465d5..7bb0bfbd 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -459,6 +459,15 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin onChange={(e) => handleRobotNameChange(e.target.value)} style={{ marginBottom: '20px' }} /> + + handleTargetUrlChange(e.target.value)} + style={{ marginBottom: '20px', marginTop: '15px' }} + /> {robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== undefined && ( Date: Tue, 18 Mar 2025 23:47:22 +0530 Subject: [PATCH 10/11] chore: lint --- src/components/robot/RobotEdit.tsx | 62 +++++++++++++++--------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 7bb0bfbd..2ea87ef6 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -126,35 +126,35 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin function extractInitialCredentials(workflow: any[]): Credentials { const credentials: Credentials = {}; - + const isPrintableCharacter = (char: string): boolean => { return char.length === 1 && !!char.match(/^[\x20-\x7E]$/); }; - + workflow.forEach(step => { if (!step.what) return; - + let currentSelector = ''; let currentValue = ''; let currentType = ''; let i = 0; - + while (i < step.what.length) { const action = step.what[i]; - + if (!action.action || !action.args?.[0]) { i++; continue; } - + const selector = action.args[0]; - + // Handle full word type actions first - if (action.action === 'type' && - action.args?.length >= 2 && + if (action.action === 'type' && + action.args?.length >= 2 && typeof action.args[1] === 'string' && - action.args[1].length > 1) { - + action.args[1].length > 1) { + if (!credentials[selector]) { credentials[selector] = { value: action.args[1], @@ -164,12 +164,12 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin i++; continue; } - + // Handle character-by-character sequences (both type and press) if ((action.action === 'type' || action.action === 'press') && action.args?.length >= 2 && typeof action.args[1] === 'string') { - + if (selector !== currentSelector) { if (currentSelector && currentValue) { credentials[currentSelector] = { @@ -181,23 +181,23 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin currentValue = credentials[selector]?.value || ''; currentType = action.args[2] || credentials[selector]?.type || 'text'; } - + const character = action.args[1]; - + if (isPrintableCharacter(character)) { currentValue += character; } else if (character === 'Backspace') { currentValue = currentValue.slice(0, -1); } - + if (!currentType && action.args[2]?.toLowerCase() === 'password') { currentType = 'password'; } - + let j = i + 1; while (j < step.what.length) { const nextAction = step.what[j]; - if (!nextAction.action || !nextAction.args?.[0] || + if (!nextAction.action || !nextAction.args?.[0] || nextAction.args[0] !== selector || (nextAction.action !== 'type' && nextAction.action !== 'press')) { break; @@ -209,18 +209,18 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin } j++; } - + credentials[currentSelector] = { value: currentValue, type: currentType }; - - i = j; + + i = j; } else { i++; } } - + if (currentSelector && currentValue) { credentials[currentSelector] = { value: currentValue, @@ -228,7 +228,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin }; } }); - + return credentials; } @@ -459,15 +459,15 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin onChange={(e) => handleRobotNameChange(e.target.value)} style={{ marginBottom: '20px' }} /> - + handleTargetUrlChange(e.target.value)} - style={{ marginBottom: '20px', marginTop: '15px' }} - /> + label="Robot Target URL" + key="Robot Target URL" + type='text' + value={targetUrl || ''} + onChange={(e) => handleTargetUrlChange(e.target.value)} + style={{ marginBottom: '20px', marginTop: '15px' }} + /> {robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== undefined && ( Date: Tue, 18 Mar 2025 23:47:51 +0530 Subject: [PATCH 11/11] chore: remove unused import --- 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 2ea87ef6..4d7e43fd 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -7,7 +7,6 @@ import { modalStyle } from "../recorder/AddWhereCondModal"; import { useGlobalInfoStore } from '../../context/globalInfo'; import { getStoredRecording, updateRecording } from '../../api/storage'; import { WhereWhatPair } from 'maxun-core'; -import { useNavigate } from 'react-router-dom'; interface RobotMeta { name: string;