Skip to content

Conversation

RohitR311
Copy link
Collaborator

@RohitR311 RohitR311 commented Sep 29, 2025

What this PR does?

closes #793

Moves the create robot UI from modal to dedicated create robot page.

image

Summary by CodeRabbit

  • New Features

    • Added a dedicated “New Data Extraction Robot” creation page with URL input, optional login flag, validation, loading state, and notifications.
    • Provides warning and discard options when another recording is active.
    • Includes helpful links to tutorials and documentation.
    • Introduced an authenticated route at /robots/create.
  • Refactor

    • Simplified the “New Recording” action in the recordings table to navigate directly to the creation page, streamlining the start-recording flow.

@RohitR311 RohitR311 requested a review from amhsirak September 29, 2025 10:45
@RohitR311 RohitR311 added Type: Enhancement Improvements to existing features Scope: UI/UX Issues/PRs related to UI/UX labels Sep 29, 2025
Copy link

coderabbitai bot commented Sep 29, 2025

Walkthrough

Adds a dedicated RobotCreate page and route (/robots/create), updates RecordingsTable to navigate directly to it, and implements the recording initiation flow within RobotCreate, including validation, optional discard of an active recording, state/session updates, and redirection.

Changes

Cohort / File(s) Summary
Routing and navigation
src/components/robot/RecordingsTable.tsx, src/pages/PageWrapper.tsx
RecordingsTable now navigates directly to /robots/create, removing prior branching and warnings; PageWrapper registers the new /robots/create route and imports RobotCreate.
Robot creation page
src/components/robot/pages/RobotCreate.tsx
New page component providing URL form, login-required option, start recording logic with capability checks, optional discard flow, session/global state updates, opening setup tab, notifications, and navigation back to /robots.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant RecordingsTable
    participant Router
    participant RobotCreate
    participant BrowserState as Browser/Recording State
    participant Session as SessionStorage
    participant Notifier as Notifications
    participant API as Backend (stopRecording)
    participant Tab as New Tab

    User->>RecordingsTable: Click "New Recording"
    RecordingsTable->>Router: navigate('/robots/create')
    Router->>RobotCreate: Render form

    User->>RobotCreate: Enter URL + Start Recording
    RobotCreate->>RobotCreate: Validate URL
    alt Invalid URL
        RobotCreate->>Notifier: Show error
    else Valid URL
        RobotCreate->>BrowserState: canCreateBrowserInState("recording")?
        alt Can create
            RobotCreate->>Session: Save browserId, recordingUrl, initialUrl, needsLogin, sessionId
            RobotCreate->>Tab: Open recording setup
            RobotCreate->>Router: navigate('/robots')
        else Blocked and active browser exists
            RobotCreate->>User: Show warning modal
            alt Discard and continue
                RobotCreate->>API: stopRecording(activeBrowserId)
                API-->>RobotCreate: ok
                RobotCreate->>Notifier: Show termination notice
                RobotCreate->>Session: Save session values
                RobotCreate->>Tab: Open recording setup
                RobotCreate->>Router: navigate('/robots')
            else Cancel
                RobotCreate-->>User: Stay on page
            end
        else Blocked, no active browser
            RobotCreate->>Notifier: Show limit notice
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

Possibly related issues

Possibly related PRs

Suggested labels

Type: Feature

Suggested reviewers

  • amhsirak

Poem

I hop to /robots/create with glee,
A fresh URL for my data spree.
If a burrow’s busy, I’ll pause—then clear—
One thump, discard; the path is clear.
Tabs pop open, whiskers twitch—
Recording starts—quick, quick, quick! 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly and concisely summarizes the primary change of relocating the create-robot functionality from a modal dialog to a standalone page, directly reflecting the core intent of the pull request without unnecessary detail or ambiguity.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch crearob-page

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/robot/RecordingsTable.tsx (1)

368-371: Add noopener,noreferrer to window.open in retrain flow.

Same tabnabbing risk exists here.

-    window.openedRecordingWindow = window.open(`/recording-setup?session=${sessionId}`, '_blank');
+    window.openedRecordingWindow = window.open(`/recording-setup?session=${sessionId}`, '_blank', 'noopener,noreferrer');
...
-    window.openedRecordingWindow = window.open(`/recording-setup?session=${sessionId}`, '_blank');
+    window.openedRecordingWindow = window.open(`/recording-setup?session=${sessionId}`, '_blank', 'noopener,noreferrer');

Also applies to: 387-390

🧹 Nitpick comments (9)
src/components/robot/pages/RobotCreate.tsx (6)

41-45: Tighten URL validation and input type.

Guard against empty/invalid/unsafe schemes and use an URL input for better UX.

-  if (!url.trim()) {
-    notify('error', 'Please enter a valid URL');
-    return;
-  }
+  const isHttpUrl = (s: string) => {
+    try {
+      const u = new URL(s);
+      return u.protocol === 'http:' || u.protocol === 'https:';
+    } catch { return false; }
+  };
+  if (!isHttpUrl(url.trim())) {
+    notify('error', t('robot_create.errors.invalid_url'));
+    return;
+  }
-              <TextField
+              <TextField
+                type="url"
                 placeholder="Example: https://www.ycombinator.com/companies/"

Also applies to: 169-176


71-76: Prefer collision-resistant session IDs.

Use crypto.randomUUID() when available.

-      const sessionId = Date.now().toString();
+      const sessionId = (window.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`);
...
-    const sessionId = Date.now().toString();
+    const sessionId = (window.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`);

Also applies to: 105-111


28-29: Remove unused imports/state.

setRecordingId, AuthContext, and user are not used.

-import { AuthContext } from '../../../context/auth';
...
-  const { setBrowserId, setRecordingUrl, notify, setRecordingId } = useGlobalInfoStore();
+  const { setBrowserId, setRecordingUrl, notify } = useGlobalInfoStore();
...
-  const { state } = React.useContext(AuthContext);
-  const { user } = state;
+  // AuthContext not needed here; remove import and usage.

Also applies to: 21-22, 36-38


197-209: Localize user‑facing strings.

Several literals bypass i18n (titles, placeholders, labels, button text, alt/aria). Replace with t(...) keys.

Example:

-          <Typography variant="h5" component="h1">
-            New Data Extraction Robot
-          </Typography>
+          <Typography variant="h5" component="h1">
+            {t('robot_create.title')}
+          </Typography>
-              {isLoading ? 'Starting...' : 'Start Recording'}
+              {isLoading ? t('robot_create.button.starting') : t('robot_create.button.start')}

Also localize: back aria-label, placeholder, checkbox label, helper section titles/descriptions, image alt.

Also applies to: 149-151, 168-176, 188-189, 216-222, 251-256, 287-291, 164-165, 145-145


169-176: Optional: prefill with current domain on focus (UX).

You can auto‑insert https:// if the user starts typing without scheme to reduce errors.


339-349: Responsive modal width.

Fixed width: '30%' can be too narrow/too wide. Use breakpoints.

-  width: '30%',
+  width: { xs: '92%', sm: 520, md: 560 },
src/pages/PageWrapper.tsx (1)

15-15: Code‑split the new page to reduce initial bundle.

Load RobotCreate lazily and wrap the route with Suspense.

-import RobotCreate from '../components/robot/pages/RobotCreate';
+const RobotCreate = React.lazy(() => import('../components/robot/pages/RobotCreate'));
-                <Route path="/robots/create" element={<RobotCreate />} />
+                <Route
+                  path="/robots/create"
+                  element={
+                    <React.Suspense fallback={null}>
+                      <RobotCreate />
+                    </React.Suspense>
+                  }
+                />

Also applies to: 98-99

src/components/robot/RecordingsTable.tsx (2)

605-639: Remove legacy “New Recording” modal and related state.

After routing to /robots/create, this modal and its state (isModalOpen, URL field, login checkbox, startRecording, setBrowserRecordingUrl) are unreachable.

-  const [isModalOpen, setModalOpen] = React.useState(false);
...
-      <GenericModal isOpen={isModalOpen} onClose={() => setModalOpen(false)} modalStyle={modalStyle}>
-        <div style={{ padding: '10px' }}>
-          <Typography variant="h6" gutterBottom>{t('recordingtable.modal.title')}</Typography>
-          <TextField
-            label={t('recordingtable.modal.label')}
-            variant="outlined"
-            fullWidth
-            value={recordingUrl}
-            onChange={setBrowserRecordingUrl}
-            style={{ marginBottom: '10px', marginTop: '20px' }}
-          />
-          <FormControlLabel
-            control={
-              <Checkbox
-                checked={isLogin}
-                onChange={(e) => setIsLogin(e.target.checked)}
-                color="primary"
-              />
-            }
-            label={t('recordingtable.modal.login_title')}
-            style={{ marginBottom: '10px' }}
-          />
-          <br />
-          <Button
-            variant="contained"
-            color="primary"
-            onClick={startRecording}
-            disabled={!recordingUrl}
-          >
-            {t('recordingtable.modal.button')}
-          </Button>
-        </div>
-      </GenericModal>

Follow‑up: remove now‑unused imports (FormControlLabel, Checkbox), state (isModalOpen, isLogin), and functions (startRecording, setBrowserRecordingUrl).

Also applies to: 154-159, 617-627, 631-637


779-789: Optional: align modal width with page modal.

Consider adopting the responsive widths suggested in RobotCreate for consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2e0324 and d98531b.

📒 Files selected for processing (3)
  • src/components/robot/RecordingsTable.tsx (1 hunks)
  • src/components/robot/pages/RobotCreate.tsx (1 hunks)
  • src/pages/PageWrapper.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/robot/pages/RobotCreate.tsx (3)
src/context/globalInfo.tsx (1)
  • useGlobalInfoStore (165-165)
src/api/recording.ts (1)
  • stopRecording (17-23)
src/components/ui/GenericModal.tsx (1)
  • GenericModal (13-29)
🔇 Additional comments (2)
src/components/robot/RecordingsTable.tsx (1)

281-283: LGTM: direct navigation to the create page.

Simplifies the flow and centralizes logic in the new page.

src/components/robot/pages/RobotCreate.tsx (1)

103-104: Drop the isLogin suggestion—no isLogin key is used anywhere; needsLogin is consistently new and has no conflicting consumers.

Likely an incorrect or invalid review comment.

Comment on lines +74 to +76
window.open(`/recording-setup?session=${sessionId}`, '_blank');
window.sessionStorage.setItem('nextTabIsRecording', 'true');

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Prevent tabnabbing: add noopener,noreferrer to window.open.

Opening a new tab without noopener lets the child tab access window.opener. Harden both opens.

-      window.open(`/recording-setup?session=${sessionId}`, '_blank');
+      window.open(`/recording-setup?session=${sessionId}`, '_blank', 'noopener,noreferrer');
...
-    window.open(`/recording-setup?session=${sessionId}`, '_blank');
+    window.open(`/recording-setup?session=${sessionId}`, '_blank', 'noopener,noreferrer');

Also applies to: 108-110

🤖 Prompt for AI Agents
In src/components/robot/pages/RobotCreate.tsx around lines 74-76 (and also apply
same change at lines 108-110), window.open is called without rel attributes so
the newly opened tab can access window.opener; update both window.open calls to
include the third argument with 'noopener,noreferrer' (or set rel via anchor
equivalent) to prevent tabnabbing and remove window.opener access, e.g., open
with window.open(url, '_blank', 'noopener,noreferrer') or use an anchor with
rel="noopener noreferrer".

Comment on lines +232 to +233
onClick={() => window.open("https://www.youtube.com/@MaxunOSS/videos", "_blank")}
>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Harden external link opens.

Add noopener,noreferrer to window.open for YouTube and docs cards.

- onClick={() => window.open("https://www.youtube.com/@MaxunOSS/videos", "_blank")}
+ onClick={() => window.open("https://www.youtube.com/@MaxunOSS/videos", "_blank", "noopener,noreferrer")}
...
- onClick={() => window.open("https://docs.maxun.dev", "_blank")}
+ onClick={() => window.open("https://docs.maxun.dev", "_blank", "noopener,noreferrer")}

Also applies to: 268-269

🤖 Prompt for AI Agents
In src/components/robot/pages/RobotCreate.tsx around lines 232-233 (and also
apply same change at 268-269), the external links opened with window.open lack
noopener and noreferrer protections; update the window.open calls to include
those flags by passing them as the third argument (e.g. window.open(url,
"_blank", "noopener,noreferrer")) and optionally nulling the opener on the
returned window (const w = window.open(...); if (w) w.opener = null) to fully
harden the external link openings.

@amhsirak amhsirak merged commit f4ab7dc into develop Sep 29, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: UI/UX Issues/PRs related to UI/UX Type: Enhancement Improvements to existing features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Move to pages for create robot

2 participants