feat: add re-run button to runs table#1026
Conversation
WalkthroughAdds a re-run feature: new i18n keys for multiple locales; a "rerun" column and button in the runs table; a propagated ChangesRerun feature
Sequence DiagramsequenceDiagram
participant User
participant UI as "RunsTable / CollapsibleRow"
participant Main as "MainPage"
participant API as "Backend API"
participant Socket as "Socket.IO Server"
User->>UI: Click Re-run button (status: success/failed/aborted)
UI->>Main: rerunHandler(robotMetaId, robotName, interpreterSettings)
Main->>API: createAndRunRecording(robotMetaId, interpreterSettings)
API-->>Main: { queued, runId, browserId? }
alt queued = true
Main->>Main: Add runId to queuedRuns
Main->>User: Show "run queued" notification
else queued = false
Main->>Main: Use browserId to open Socket.IO connection
Main->>Socket: Listen for 'run-completed'
Socket-->>Main: 'run-completed'(data.status)
Main->>API: Invalidate runs cache
alt data.status = success
Main->>User: Show success notification
else
Main->>User: Show failure notification
end
end
Main->>User: Navigate to /runs/{robotMetaId}/run/{runId}
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/components/run/ColapsibleRow.tsx`:
- Around line 214-227: The collapsed detail row's TableCell still uses a fixed
colSpan (colSpan={6}) which no longer matches the updated columns after adding
the 'rerun' column; update the TableCell that renders the expanded content in
ColapsibleRow.tsx to compute colSpan dynamically (e.g., colSpan={columns.length}
or colSpan={columns.filter(c => !c.hidden).length} if you track visibility)
instead of a hardcoded 6 so the expanded content spans the correct number of
columns; locate the TableCell with the colSpan prop in the collapsed content
rendering and replace the literal with the dynamic expression.
- Around line 218-223: The IconButton's aria-label is hardcoded ("rerun");
update ColapsibleRow.tsx to use the app's i18n translation function so
screen-readers get localized text: import/use the existing translation hook
(e.g. useTranslation/t) and change the IconButton prop aria-label to a
translated string (aria-label={t('rerun') or the appropriate key}), keeping the
onClick handler (rerunHandler(row.robotMetaId, row.name,
row.interpreterSettings)) intact so behavior is unchanged.
In `@src/components/run/RunsTable.tsx`:
- Line 29: The new "Re-run" column in RunsTable uses the wrong i18n key
namespace (it references runs_table.rerun) causing fallbacks; update the column
definition with id 'rerun' and any usages (e.g., the header label lookup and the
cell rendering around the rerun column) to use the existing translation key
runstable.rerun consistently (or alternatively add runs_table.rerun to the
locales), ensuring both the column descriptor and the render code reference the
same key.
In `@src/pages/MainPage.tsx`:
- Around line 229-265: In handleReRunRecording, validate the response from
createAndRunRecording (the CreateRunResponseWithQueue returned object) before
navigating or creating sockets: check that runId is non-empty (and for the
socket path that browserId is non-empty) and that queued is a boolean; if
runId/browserId are empty or queued is unexpectedly false for a failed response,
call notify('error', ...) and return early to avoid navigating to /run/ with an
empty id or opening sockets to `${apiUrl}/`. Also mirror the socket lifecycle
handlers from handleRunRecording by adding socket.on('connect_error', ...) and
socket.on('disconnect', ...) when you create the socket (the socket variable in
the non-queued path) so connection failures are handled and the socket is
cleaned up.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5062d0b4-ac59-4914-8816-fd58a128ba97
📒 Files selected for processing (10)
public/locales/de.jsonpublic/locales/en.jsonpublic/locales/es.jsonpublic/locales/ja.jsonpublic/locales/tr.jsonpublic/locales/zh.jsonsrc/components/run/ColapsibleRow.tsxsrc/components/run/Runs.tsxsrc/components/run/RunsTable.tsxsrc/pages/MainPage.tsx
| { id: 'startedAt', label: 'Started At', minWidth: 80 }, | ||
| { id: 'finishedAt', label: 'Finished At', minWidth: 80 }, | ||
| { id: 'settings', label: 'Settings', minWidth: 80 }, | ||
| { id: 'rerun', label: 'Re-run', minWidth: 80 }, |
There was a problem hiding this comment.
Fix i18n namespace mismatch for the new Re-run column header.
The column is translated via runstable.rerun, but this PR adds runs_table.rerun; in non-English locales the header will fall back to "Re-run" instead of using localized text.
🔧 Proposed fix
export const columns: readonly Column[] = [
{ id: 'runStatus', label: 'Status', minWidth: 80 },
{ id: 'name', label: 'Name', minWidth: 80 },
{ id: 'startedAt', label: 'Started At', minWidth: 80 },
{ id: 'finishedAt', label: 'Finished At', minWidth: 80 },
{ id: 'settings', label: 'Settings', minWidth: 80 },
{ id: 'rerun', label: 'Re-run', minWidth: 80 },
{ id: 'delete', label: 'Delete', minWidth: 80 },
];
const translatedColumns = useMemo(() =>
columns.map(column => ({
...column,
- label: t(`runstable.${column.id}`, column.label)
+ label: t(
+ column.id === 'rerun' ? 'runs_table.rerun' : `runstable.${column.id}`,
+ column.label
+ )
})),
[t]
);Also applies to: 132-136
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/run/RunsTable.tsx` at line 29, The new "Re-run" column in
RunsTable uses the wrong i18n key namespace (it references runs_table.rerun)
causing fallbacks; update the column definition with id 'rerun' and any usages
(e.g., the header label lookup and the cell rendering around the rerun column)
to use the existing translation key runstable.rerun consistently (or
alternatively add runs_table.rerun to the locales), ensuring both the column
descriptor and the render code reference the same key.
29a0dad to
7d9424c
Compare
|
Hi team — just a gentle ping on this PR. All checks are passing. Would appreciate a review when you get a chance. Happy to address any feedback. Thanks! |
Adds a Replay icon button in the runs table for completed runs (success, failed, aborted). Clicking it re-triggers the same robot with its original interpreter settings and navigates to the new run. Changes: - ColapsibleRow: add rerun case with Tooltip-wrapped Replay icon (terminal states only) - ColapsibleRow: use columns.length for dynamic colSpan instead of hardcoded 6 - RunsTable: add rerun column, prop threading, fix useCallback deps - Runs: thread rerunHandler prop - MainPage: add handleReRunRecording with runId/browserId validation, connect_error/disconnect socket handlers, correct queued notify message - Locales: add runstable.rerun and runs_table.rerun keys to all 6 languages Closes getmaxun#687
7d9424c to
4c0b126
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/pages/MainPage.tsx`:
- Around line 261-263: The toast for queued reruns is hardcoded in English;
update the notify call inside the queued branch (where queued is truthy and
setQueuedRuns is called with runId) to use an i18n lookup instead of the literal
string (reference notify(..., `Run queued: ${robotName}`) in MainPage.tsx), and
add the corresponding locale key/value entries to the translation files used by
the app so all supported locales show the translated message that can
interpolate robotName. Ensure you call the translation helper the project uses
(e.g., t or i18n.t) and pass robotName as the interpolation parameter.
- Around line 264-267: The rerun path incorrectly treats
CreateRunResponse.browserId === null as a failure and shows notify('error',
t('main_page.notifications.run_start_failed', { name: robotName })); but
handleRunRecording and other logic already treat browserId === null as a valid
browserless run; change the condition so it only errors when there is no runId
(or browserId is undefined/unset) rather than when browserId === null — e.g.,
check response.runId (or use strict undefined check for browserId) and remove
the notify/return for the null-browser case so browserless reruns proceed to
handleRunRecording/navigation as intended (refer to CreateRunResponse.browserId,
handleRunRecording, notify, run_start_failed, robotName).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0d458e21-643a-4311-b656-0e502735f7ac
📒 Files selected for processing (10)
public/locales/de.jsonpublic/locales/en.jsonpublic/locales/es.jsonpublic/locales/ja.jsonpublic/locales/tr.jsonpublic/locales/zh.jsonsrc/components/run/ColapsibleRow.tsxsrc/components/run/Runs.tsxsrc/components/run/RunsTable.tsxsrc/pages/MainPage.tsx
✅ Files skipped from review due to trivial changes (2)
- public/locales/tr.json
- public/locales/en.json
🚧 Files skipped from review as they are similar to previous changes (6)
- src/components/run/Runs.tsx
- public/locales/zh.json
- src/components/run/ColapsibleRow.tsx
- public/locales/ja.json
- public/locales/de.json
- src/components/run/RunsTable.tsx
| if (queued) { | ||
| setQueuedRuns(prev => new Set([...prev, runId])); | ||
| notify('info', `Run queued: ${robotName}`); |
There was a problem hiding this comment.
Localize the queued rerun toast.
This branch still emits a hardcoded English notification, so the rerun flow is only partially translated even though this PR adds locale coverage for the feature. Please move this behind an i18n key and add the matching locale entries.
Suggested change
- notify('info', `Run queued: ${robotName}`);
+ notify('info', t('main_page.notifications.run_queued', { name: robotName }));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (queued) { | |
| setQueuedRuns(prev => new Set([...prev, runId])); | |
| notify('info', `Run queued: ${robotName}`); | |
| if (queued) { | |
| setQueuedRuns(prev => new Set([...prev, runId])); | |
| notify('info', t('main_page.notifications.run_queued', { name: robotName })); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/MainPage.tsx` around lines 261 - 263, The toast for queued reruns
is hardcoded in English; update the notify call inside the queued branch (where
queued is truthy and setQueuedRuns is called with runId) to use an i18n lookup
instead of the literal string (reference notify(..., `Run queued: ${robotName}`)
in MainPage.tsx), and add the corresponding locale key/value entries to the
translation files used by the app so all supported locales show the translated
message that can interpolate robotName. Ensure you call the translation helper
the project uses (e.g., t or i18n.t) and pass robotName as the interpolation
parameter.
| } else { | ||
| if (!browserId) { | ||
| notify('error', t('main_page.notifications.run_start_failed', { name: robotName })); | ||
| return; |
There was a problem hiding this comment.
Handle successful reruns that do not allocate a browser.
CreateRunResponse.browserId is nullable in this file, and handleRunRecording already treats browserId === null as a valid response. This rerun path turns the same case into run_start_failed, so browserless/immediate reruns will show a failure toast after a real runId was created and Line 259 already navigated to it.
Suggested change
- } else {
- if (!browserId) {
- notify('error', t('main_page.notifications.run_start_failed', { name: robotName }));
- return;
- }
-
+ } else if (browserId) {
const socket = io(`${apiUrl}/${browserId}`, {
transports: ["websocket", "polling"],
rejectUnauthorized: false
});
setSockets(sockets => [...sockets, socket]);
@@
notify('info', t('main_page.notifications.run_started', { name: robotName }));
+ } else {
+ notify('info', t('main_page.notifications.run_started', { name: robotName }));
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| } else { | |
| if (!browserId) { | |
| notify('error', t('main_page.notifications.run_start_failed', { name: robotName })); | |
| return; | |
| } else if (browserId) { | |
| const socket = io(`${apiUrl}/${browserId}`, { | |
| transports: ["websocket", "polling"], | |
| rejectUnauthorized: false | |
| }); | |
| setSockets(sockets => [...sockets, socket]); | |
| socket.on('run-completed', (data) => { | |
| setRerenderRuns(true); | |
| invalidateRuns(); | |
| if (data.status === 'success') { | |
| notify('success', t('main_page.notifications.interpretation_success', { name: robotName })); | |
| } else { | |
| notify('error', t('main_page.notifications.interpretation_failed', { name: robotName })); | |
| } | |
| }); | |
| socket.on('connect_error', (error) => { | |
| console.log('error', `Failed to connect to browser ${browserId}: ${error}`); | |
| notify('error', t('main_page.notifications.connection_failed', { name: robotName })); | |
| }); | |
| socket.on('disconnect', (reason) => { | |
| console.log('warn', `Disconnected from browser ${browserId}: ${reason}`); | |
| }); | |
| notify('info', t('main_page.notifications.run_started', { name: robotName })); | |
| } else { | |
| notify('info', t('main_page.notifications.run_started', { name: robotName })); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/pages/MainPage.tsx` around lines 264 - 267, The rerun path incorrectly
treats CreateRunResponse.browserId === null as a failure and shows
notify('error', t('main_page.notifications.run_start_failed', { name: robotName
})); but handleRunRecording and other logic already treat browserId === null as
a valid browserless run; change the condition so it only errors when there is no
runId (or browserId is undefined/unset) rather than when browserId === null —
e.g., check response.runId (or use strict undefined check for browserId) and
remove the notify/return for the null-browser case so browserless reruns proceed
to handleRunRecording/navigation as intended (refer to
CreateRunResponse.browserId, handleRunRecording, notify, run_start_failed,
robotName).
Summary
success,failed,aborted) — not for active or queued onesmaxConcurrency,maxRepeats,debugflags)runs_table.rerunadded for all 6 supported languages (en, de, es, ja, tr, zh)Closes #687
Changes
ColapsibleRow.tsx— newreruncolumn case withReplayicon, only rendered for terminal run statesRunsTable.tsx— addedreruncolumn definition andrerunHandlerpropRuns.tsx— threadsrerunHandlerprop down toRunsTableMainPage.tsx—handleReRunRecordinghandler using existingcreateAndRunRecordingAPIpublic/locales/*.json—runs_table.rerunkey in all localesTest plan
success,failed, andabortedrunsrunningorqueuedrunsSummary by CodeRabbit
New Features
Internationalization
Enhancement