From d98531b8381714e15c99dd43db9fd5b6837ff782 Mon Sep 17 00:00:00 2001 From: Rohit Rajan Date: Mon, 29 Sep 2025 16:14:16 +0530 Subject: [PATCH] feat: move robot create modal to page --- src/components/robot/RecordingsTable.tsx | 16 +- src/components/robot/pages/RobotCreate.tsx | 349 +++++++++++++++++++++ src/pages/PageWrapper.tsx | 2 + 3 files changed, 353 insertions(+), 14 deletions(-) create mode 100644 src/components/robot/pages/RobotCreate.tsx diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 42c5971b..7055c9fa 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -278,20 +278,8 @@ export const RecordingsTable = ({ }, [setRecordings, notify, t]); const handleNewRecording = useCallback(async () => { - const canCreateRecording = await canCreateBrowserInState("recording"); - - if (!canCreateRecording) { - const activeBrowserId = await getActiveBrowserId(); - if (activeBrowserId) { - setActiveBrowserId(activeBrowserId); - setWarningModalOpen(true); - } else { - notify('warning', t('recordingtable.notifications.browser_limit_warning')); - } - } else { - setModalOpen(true); - } - }, []); + navigate('/robots/create'); + }, [navigate]); const notifyRecordingTabsToClose = (browserId: string) => { const closeMessage = { diff --git a/src/components/robot/pages/RobotCreate.tsx b/src/components/robot/pages/RobotCreate.tsx new file mode 100644 index 00000000..70058642 --- /dev/null +++ b/src/components/robot/pages/RobotCreate.tsx @@ -0,0 +1,349 @@ +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; +import { + Box, + Typography, + TextField, + Button, + FormControlLabel, + Checkbox, + IconButton, + Grid, + Card, + CircularProgress, + Container, + CardContent +} from '@mui/material'; +import { ArrowBack, PlayCircleOutline, Article } from '@mui/icons-material'; +import { useGlobalInfoStore } from '../../../context/globalInfo'; +import { canCreateBrowserInState, getActiveBrowserId, stopRecording } from '../../../api/recording'; +import { AuthContext } from '../../../context/auth'; +import { GenericModal } from '../../ui/GenericModal'; + + +const RobotCreate: React.FC = () => { + const { t } = useTranslation(); + const navigate = useNavigate(); + const { setBrowserId, setRecordingUrl, notify, setRecordingId } = useGlobalInfoStore(); + + const [url, setUrl] = useState(''); + const [needsLogin, setNeedsLogin] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [isWarningModalOpen, setWarningModalOpen] = useState(false); + const [activeBrowserId, setActiveBrowserId] = useState(''); + + const { state } = React.useContext(AuthContext); + const { user } = state; + + + const handleStartRecording = async () => { + if (!url.trim()) { + notify('error', 'Please enter a valid URL'); + return; + } + + setIsLoading(true); + + try { + const canCreateRecording = await canCreateBrowserInState("recording"); + + if (!canCreateRecording) { + const activeBrowser = await getActiveBrowserId(); + if (activeBrowser) { + setActiveBrowserId(activeBrowser); + setWarningModalOpen(true); + } else { + notify('warning', t('recordingtable.notifications.browser_limit_warning')); + } + setIsLoading(false); + return; + } + + setBrowserId('new-recording'); + setRecordingUrl(url); + + window.sessionStorage.setItem('browserId', 'new-recording'); + window.sessionStorage.setItem('recordingUrl', url); + window.sessionStorage.setItem('initialUrl', url); + window.sessionStorage.setItem('needsLogin', needsLogin.toString()); + + const sessionId = Date.now().toString(); + window.sessionStorage.setItem('recordingSessionId', sessionId); + + window.open(`/recording-setup?session=${sessionId}`, '_blank'); + window.sessionStorage.setItem('nextTabIsRecording', 'true'); + + // Reset loading state immediately after opening new tab + setIsLoading(false); + navigate('/robots'); + } catch (error) { + console.error('Error starting recording:', error); + notify('error', 'Failed to start recording. Please try again.'); + setIsLoading(false); + } + }; + + const handleDiscardAndCreate = async () => { + if (activeBrowserId) { + await stopRecording(activeBrowserId); + notify('warning', t('browser_recording.notifications.terminated')); + } + + setWarningModalOpen(false); + setIsLoading(false); + + // Continue with the original Recording logic + setBrowserId('new-recording'); + setRecordingUrl(url); + + window.sessionStorage.setItem('browserId', 'new-recording'); + window.sessionStorage.setItem('recordingUrl', url); + window.sessionStorage.setItem('initialUrl', url); + window.sessionStorage.setItem('needsLogin', needsLogin.toString()); + + const sessionId = Date.now().toString(); + window.sessionStorage.setItem('recordingSessionId', sessionId); + + window.open(`/recording-setup?session=${sessionId}`, '_blank'); + window.sessionStorage.setItem('nextTabIsRecording', 'true'); + + navigate('/robots'); + }; + + + + + + + return ( + + + + navigate('/robots')} + sx={{ + ml: -1, + mr: 1, + color: theme => theme.palette.text.primary, + backgroundColor: 'transparent !important', + '&:hover': { + backgroundColor: 'transparent !important', + }, + '&:active': { + backgroundColor: 'transparent !important', + }, + '&:focus': { + backgroundColor: 'transparent !important', + }, + '&:focus-visible': { + backgroundColor: 'transparent !important', + }, + }} + disableRipple + aria-label="Go back" + > + + + + New Data Extraction Robot + + + + + + {/* Logo (kept as original) */} + Maxun Logo + + {/* Origin URL Input */} + + setUrl(e.target.value)} + /> + + + {/* Checkbox */} + + setNeedsLogin(e.target.checked)} + color="primary" + /> + } + label="This website needs logging in." + /> + + + {/* Button */} + + + + + + + + + First time creating a robot? + + + Get help and learn how to use Maxun effectively. + + + + + {/* YouTube Tutorials */} + + window.open("https://www.youtube.com/@MaxunOSS/videos", "_blank")} + > + + theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.54)' : '', + }} + > + + + + + Video Tutorials + + + Watch step-by-step guides + + + + + + + {/* Documentation */} + + window.open("https://docs.maxun.dev", "_blank")} + > + + theme.palette.mode === 'light' ? 'rgba(0, 0, 0, 0.54)' : '', + }} + > +
+ + + + Documentation + + + Explore detailed guides + + + + + + + + + + + { + setWarningModalOpen(false); + setIsLoading(false); + }} modalStyle={modalStyle}> +
+ {t('recordingtable.warning_modal.title')} + + {t('recordingtable.warning_modal.message')} + + + + + + +
+
+ + + + ); +}; + +export default RobotCreate; + +const modalStyle = { + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '30%', + backgroundColor: 'background.paper', + p: 4, + height: 'fit-content', + display: 'block', + padding: '20px', +}; \ No newline at end of file diff --git a/src/pages/PageWrapper.tsx b/src/pages/PageWrapper.tsx index e7361b2f..e257367b 100644 --- a/src/pages/PageWrapper.tsx +++ b/src/pages/PageWrapper.tsx @@ -12,6 +12,7 @@ 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 RobotCreate from '../components/robot/pages/RobotCreate'; export const PageWrapper = () => { const [open, setOpen] = useState(false); @@ -94,6 +95,7 @@ export const PageWrapper = () => { }> } /> + } /> } /> } /> } />