diff --git a/src/components/robot/RobotEdit.tsx b/src/components/robot/RobotEdit.tsx index 946af330..7d4e179e 100644 --- a/src/components/robot/RobotEdit.tsx +++ b/src/components/robot/RobotEdit.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { GenericModal } from "../ui/GenericModal"; -import { TextField, Typography, Box, Button } from "@mui/material"; +import { TextField, Typography, Box, Button, IconButton, InputAdornment } from "@mui/material"; +import { Visibility, VisibilityOff } from '@mui/icons-material'; import { modalStyle } from "../recorder/AddWhereCondModal"; import { useGlobalInfoStore } from '../../context/globalInfo'; import { getStoredRecording, updateRecording } from '../../api/storage'; @@ -25,6 +26,14 @@ interface RobotEditOptions { limit?: number; } +interface Credentials { + [key: string]: string; +} + +interface CredentialVisibility { + [key: string]: boolean; +} + interface ScheduleConfig { runEvery: number; runEveryUnit: 'MINUTES' | 'HOURS' | 'DAYS' | 'WEEKS' | 'MONTHS'; @@ -48,6 +57,7 @@ export interface RobotSettings { google_access_token?: string | null; google_refresh_token?: string | null; schedule?: ScheduleConfig | null; + isLogin?: boolean; } interface RobotSettingsProps { @@ -60,7 +70,17 @@ interface RobotSettingsProps { export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettings }: RobotSettingsProps) => { const { t } = useTranslation(); const [robot, setRobot] = useState(null); + const [credentials, setCredentials] = useState({}); const { recordingId, notify } = useGlobalInfoStore(); + const [credentialSelectors, setCredentialSelectors] = useState([]); + const [showPasswords, setShowPasswords] = useState({}); + + const handleClickShowPassword = (selector: string) => { + setShowPasswords(prev => ({ + ...prev, + [selector]: !prev[selector] + })); + }; useEffect(() => { if (isOpen) { @@ -68,6 +88,39 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin } }, [isOpen]); + useEffect(() => { + if (robot?.recording?.workflow) { + const selectors = findCredentialSelectors(robot.recording.workflow); + setCredentialSelectors(selectors); + + // Initialize credentials state + const initialCredentials: Record = {}; + selectors.forEach(selector => { + initialCredentials[selector] = ''; + }); + setCredentials(initialCredentials); + } + }, [robot]); + + const findCredentialSelectors = (workflow: WhereWhatPair[]): string[] => { + const selectors = new Set(); + + workflow?.forEach(step => { + step.what?.forEach(action => { + if ( + (action.action === 'type' || action.action === 'press') && + action.args && + action.args[0] && + typeof action.args[0] === 'string' + ) { + selectors.add(action.args[0]); + } + }); + }); + + return Array.from(selectors); + }; + const getRobot = async () => { if (recordingId) { const robot = await getStoredRecording(recordingId); @@ -83,6 +136,13 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin ); }; + const handleCredentialChange = (selector: string, value: string) => { + setCredentials(prev => ({ + ...prev, + [selector]: value + })); + }; + const handleLimitChange = (newLimit: number) => { setRobot((prev) => { if (!prev) return prev; @@ -111,6 +171,7 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin const payload = { name: robot.recording_meta.name, limit: robot.recording.workflow[0]?.what[0]?.args?.[0]?.limit, + credentials: credentials, }; const success = await updateRecording(robot.recording_meta.id, payload); @@ -170,6 +231,38 @@ export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettin /> )} + {(robot.isLogin && credentialSelectors.length > 0) && ( + <> + + {t('Login Credentials')} + + + {credentialSelectors.map((selector) => ( + handleCredentialChange(selector, e.target.value)} + style={{ marginBottom: '20px' }} + InputProps={{ + endAdornment: ( + + handleClickShowPassword(selector)} + edge="end" + > + {showPasswords[selector] ? : } + + + ), + }} + /> + ))} + + )} +