Skip to content

Commit 29a0dad

Browse files
feat: add re-run button to runs table
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. - ColapsibleRow: add rerun case with Replay icon (terminal states only) - RunsTable: add rerun column + prop threading - Runs: thread rerunHandler prop - MainPage: add handleReRunRecording handler - Locales: add runs_table.rerun key to all 6 languages Closes #687
1 parent 38bf3a8 commit 29a0dad

10 files changed

Lines changed: 1914 additions & 1848 deletions

File tree

public/locales/de.json

Lines changed: 622 additions & 621 deletions
Large diffs are not rendered by default.

public/locales/en.json

Lines changed: 601 additions & 600 deletions
Large diffs are not rendered by default.

public/locales/es.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@
575575
"run_by_api": "Ejecutado por API",
576576
"run_type": "Tipo de Ejecución"
577577
}
578-
}
578+
},
579+
"rerun": "Re-ejecutar"
579580
},
580581
"run_content": {
581582
"tabs": {
@@ -648,4 +649,4 @@
648649
"de": "Alemán",
649650
"tr": "Turco"
650651
}
651-
}
652+
}

public/locales/ja.json

Lines changed: 616 additions & 615 deletions
Large diffs are not rendered by default.

public/locales/tr.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@
461461
"robot_settings": {
462462
"title": "Robot Ayarları",
463463
"target_url": "Robot Hedef URL",
464-
"new_name": "Robot Adı",
464+
"new_name": "Robot Adı",
465465
"robot_id": "Robot ID",
466466
"robot_limit": "Robot Limiti",
467467
"created_by_user": "Oluşturan",
@@ -576,7 +576,8 @@
576576
"run_by_api": "API",
577577
"run_type": "Tür"
578578
}
579-
}
579+
},
580+
"rerun": "Yeniden Çalıştır"
580581
},
581582
"run_content": {
582583
"tabs": {
@@ -649,4 +650,4 @@
649650
"de": "Almanca",
650651
"tr": "Türkçe"
651652
}
652-
}
653+
}

public/locales/zh.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@
461461
"robot_settings": {
462462
"title": "机器人设置",
463463
"target_url": "机器人目标URL",
464-
"new_name": "机器人名称",
464+
"new_name": "机器人名称",
465465
"robot_id": "机器人ID",
466466
"robot_limit": "机器人限制",
467467
"created_by_user": "由用户创建",
@@ -576,7 +576,8 @@
576576
"run_by_api": "由API运行",
577577
"run_type": "运行类型"
578578
}
579-
}
579+
},
580+
"rerun": "重新运行"
580581
},
581582
"run_content": {
582583
"tabs": {
@@ -649,4 +650,4 @@
649650
"de": "德语",
650651
"tr": "土耳其语"
651652
}
652-
}
653+
}

src/components/run/ColapsibleRow.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import TableRow from "@mui/material/TableRow";
44
import TableCell from "@mui/material/TableCell";
55
import { Box, Collapse, IconButton, Typography, Chip, TextField } from "@mui/material";
66
import { Button } from "@mui/material";
7-
import { DeleteForever, KeyboardArrowDown, KeyboardArrowUp, Settings } from "@mui/icons-material";
7+
import { DeleteForever, KeyboardArrowDown, KeyboardArrowUp, Replay, Settings } from "@mui/icons-material";
88
import { deleteRunFromStorage } from "../../api/storage";
99
import { columns, Data } from "./RunsTable";
1010
import { RunContent } from "./RunContent";
@@ -76,10 +76,11 @@ interface CollapsibleRowProps {
7676
onToggleExpanded: (shouldExpand: boolean) => void;
7777
currentLog: string;
7878
abortRunHandler: (runId: string, robotName: string, browserId: string) => void;
79+
rerunHandler: (robotMetaId: string, robotName: string, interpreterSettings: any) => void;
7980
runningRecordingName: string;
8081
urlRunId: string | null;
8182
}
82-
export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, currentLog, abortRunHandler, runningRecordingName, urlRunId }: CollapsibleRowProps) => {
83+
export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, currentLog, abortRunHandler, rerunHandler, runningRecordingName, urlRunId }: CollapsibleRowProps) => {
8384
const { t } = useTranslation();
8485
const theme = useTheme();
8586
const [isDeleteOpen, setDeleteOpen] = useState(false);
@@ -210,6 +211,20 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, cu
210211
{row.status === 'aborted' && <Chip label={t('runs_table.run_status_chips.aborted')} color="error" variant="outlined" />}
211212
</TableCell>
212213
)
214+
case 'rerun':
215+
return (
216+
<TableCell key={column.id} align={column.align}>
217+
{['success', 'failed', 'aborted'].includes(row.status) && (
218+
<IconButton
219+
aria-label="rerun"
220+
size="small"
221+
onClick={() => rerunHandler(row.robotMetaId, row.name, row.interpreterSettings)}
222+
>
223+
<Replay />
224+
</IconButton>
225+
)}
226+
</TableCell>
227+
);
213228
case 'delete':
214229
return (
215230
<TableCell key={column.id} align={column.align}>

src/components/run/Runs.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@ import { RunsTable } from "./RunsTable";
55
interface RunsProps {
66
currentInterpretationLog: string;
77
abortRunHandler: (runId: string, robotName: string, browserId: string) => void;
8+
rerunHandler: (robotMetaId: string, robotName: string, interpreterSettings: any) => void;
89
runId: string;
910
runningRecordingName: string;
1011
}
1112

1213
export const Runs = (
13-
{ currentInterpretationLog, abortRunHandler, runId, runningRecordingName }: RunsProps) => {
14+
{ currentInterpretationLog, abortRunHandler, rerunHandler, runId, runningRecordingName }: RunsProps) => {
1415

1516
return (
1617
<Grid container direction="column" sx={{ padding: '30px' }}>
1718
<Grid item xs>
1819
<RunsTable
1920
currentInterpretationLog={currentInterpretationLog}
2021
abortRunHandler={abortRunHandler}
22+
rerunHandler={rerunHandler}
2123
runId={runId}
2224
runningRecordingName={runningRecordingName}
2325
/>

src/components/run/RunsTable.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const columns: readonly Column[] = [
2626
{ id: 'startedAt', label: 'Started At', minWidth: 80 },
2727
{ id: 'finishedAt', label: 'Finished At', minWidth: 80 },
2828
{ id: 'settings', label: 'Settings', minWidth: 80 },
29+
{ id: 'rerun', label: 'Re-run', minWidth: 80 },
2930
{ id: 'delete', label: 'Delete', minWidth: 80 },
3031
];
3132

@@ -39,7 +40,7 @@ interface AccordionSortConfig {
3940
}
4041

4142
interface Column {
42-
id: 'runStatus' | 'name' | 'startedAt' | 'finishedAt' | 'delete' | 'settings';
43+
id: 'runStatus' | 'name' | 'startedAt' | 'finishedAt' | 'delete' | 'settings' | 'rerun';
4344
label: string;
4445
minWidth?: number;
4546
align?: 'right';
@@ -69,6 +70,7 @@ export interface Data {
6970
interface RunsTableProps {
7071
currentInterpretationLog: string;
7172
abortRunHandler: (runId: string, robotName: string, browserId: string) => void;
73+
rerunHandler: (robotMetaId: string, robotName: string, interpreterSettings: any) => void;
7274
runId: string;
7375
runningRecordingName: string;
7476
}
@@ -83,6 +85,7 @@ interface PaginationState {
8385
export const RunsTable: React.FC<RunsTableProps> = ({
8486
currentInterpretationLog,
8587
abortRunHandler,
88+
rerunHandler,
8689
runId,
8790
runningRecordingName
8891
}) => {
@@ -470,6 +473,7 @@ export const RunsTable: React.FC<RunsTableProps> = ({
470473
onToggleExpanded={(shouldExpand) => handleRowExpand(row.runId, row.robotMetaId, shouldExpand)}
471474
currentLog={currentInterpretationLog}
472475
abortRunHandler={abortRunHandler}
476+
rerunHandler={rerunHandler}
473477
runningRecordingName={runningRecordingName}
474478
urlRunId={urlRunId}
475479
/>

src/pages/MainPage.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,44 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
226226
};
227227
}, []);
228228

229+
const handleReRunRecording = useCallback((robotMetaId: string, robotName: string, interpreterSettings: RunSettings) => {
230+
createAndRunRecording(robotMetaId, interpreterSettings).then((response: CreateRunResponseWithQueue) => {
231+
invalidateRuns();
232+
const { browserId, runId, queued } = response;
233+
234+
navigate(`/runs/${robotMetaId}/run/${runId}`);
235+
236+
if (queued) {
237+
setQueuedRuns(prev => new Set([...prev, runId]));
238+
notify('info', t('main_page.notifications.run_started', { name: robotName }));
239+
} else {
240+
const socket = io(`${apiUrl}/${browserId}`, {
241+
transports: ["websocket", "polling"],
242+
rejectUnauthorized: false
243+
});
244+
245+
setSockets(sockets => [...sockets, socket]);
246+
247+
socket.on('run-completed', (data) => {
248+
setRerenderRuns(true);
249+
invalidateRuns();
250+
if (data.status === 'success') {
251+
notify('success', t('main_page.notifications.interpretation_success', { name: robotName }));
252+
} else {
253+
notify('error', t('main_page.notifications.interpretation_failed', { name: robotName }));
254+
}
255+
});
256+
257+
notify('info', t('main_page.notifications.run_started', { name: robotName }));
258+
}
259+
260+
setContent('runs');
261+
}).catch((error: any) => {
262+
notify('error', t('main_page.notifications.run_start_failed', { name: robotName }));
263+
console.error('Error in rerun:', error);
264+
});
265+
}, [navigate, notify, t, invalidateRuns, setRerenderRuns, setQueuedRuns]);
266+
229267
const handleScheduleRecording = async (settings: ScheduleSettings) => {
230268
const { message, runId }: ScheduleRunResponse = await scheduleStoredRecording(runningRecordingId, settings);
231269
if (message === 'success') {
@@ -310,6 +348,7 @@ export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps)
310348
return <Runs
311349
currentInterpretationLog={currentInterpretationLog}
312350
abortRunHandler={abortRunHandler}
351+
rerunHandler={handleReRunRecording}
313352
runId={ids.runId}
314353
runningRecordingName={runningRecordingName}
315354
/>;

0 commit comments

Comments
 (0)