diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 504cfa43..f06270ed 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -42,6 +42,7 @@ import { Add } from "@mui/icons-material"; import { useNavigate } from 'react-router-dom'; import { canCreateBrowserInState, getActiveBrowserId, stopRecording } from "../../api/recording"; import { GenericModal } from '../ui/GenericModal'; +import { useTheme } from '@mui/material/styles'; declare global { interface Window { @@ -148,12 +149,15 @@ export const RecordingsTable = ({ handleEditRobot, handleDuplicateRobot }: RecordingsTableProps) => { const { t } = useTranslation(); + const theme = useTheme(); const [page, setPage] = React.useState(0); const [rowsPerPage, setRowsPerPage] = React.useState(10); const { data: recordingsData = [], isLoading: isFetching, error, refetch } = useCachedRecordings(); const [isModalOpen, setModalOpen] = React.useState(false); const [searchTerm, setSearchTerm] = React.useState(''); const [isWarningModalOpen, setWarningModalOpen] = React.useState(false); + const [isDeleteConfirmOpen, setDeleteConfirmOpen] = React.useState(false); + const [pendingDeleteId, setPendingDeleteId] = React.useState(null); const [activeBrowserId, setActiveBrowserId] = React.useState(''); const columns = useMemo(() => [ @@ -431,6 +435,32 @@ export const RecordingsTable = ({ return filteredRows.slice(start, start + rowsPerPage); }, [filteredRows, page, rowsPerPage]); + const openDeleteConfirm = React.useCallback((id: string) => { + setPendingDeleteId(String(id)); + setDeleteConfirmOpen(true); + }, []); + + const confirmDeleteRecording = React.useCallback(async () => { + if (!pendingDeleteId) return; + const hasRuns = await checkRunsForRecording(pendingDeleteId); + if (hasRuns) { + notify('warning', t('recordingtable.notifications.delete_warning')); + setDeleteConfirmOpen(false); + setPendingDeleteId(null); + return; + } + + const success = await deleteRecordingFromStorage(pendingDeleteId); + if (success) { + notify('success', t('recordingtable.notifications.delete_success')); + refetch(); + } + setDeleteConfirmOpen(false); + setPendingDeleteId(null); + }, [pendingDeleteId, notify, t, refetch]); + + const pendingRow = pendingDeleteId ? rows.find(r => String(r.id) === pendingDeleteId) : null; + const handlers = useMemo(() => ({ handleRunRecording, handleScheduleRecording, @@ -439,19 +469,7 @@ export const RecordingsTable = ({ handleEditRobot, handleDuplicateRobot, handleRetrainRobot, - handleDelete: async (id: string) => { - const hasRuns = await checkRunsForRecording(id); - if (hasRuns) { - notify('warning', t('recordingtable.notifications.delete_warning')); - return; - } - - const success = await deleteRecordingFromStorage(id); - if (success) { - notify('success', t('recordingtable.notifications.delete_success')); - refetch(); - } - } + handleDelete: async (id: string) => openDeleteConfirm(id) }), [handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording, handleEditRobot, handleDuplicateRobot, handleRetrainRobot, notify, t, refetch]); return ( @@ -628,6 +646,33 @@ export const RecordingsTable = ({ + { setDeleteConfirmOpen(false); setPendingDeleteId(null); }} + modalStyle={{ ...modalStyle, padding: 0, backgroundColor: 'transparent', width: 'auto', maxWidth: '520px' }} + > + + + + {t('recordingtable.delete_confirm.title', { name: pendingRow?.name, defaultValue: 'Delete {{name}}?' })} + + + {t('recordingtable.delete_confirm.message', { + name: pendingRow?.name, + defaultValue: 'Are you sure you want to delete the robot "{{name}}"?' + })} + + + + + + + + ); } diff --git a/src/components/run/ColapsibleRow.tsx b/src/components/run/ColapsibleRow.tsx index bf6e9c40..63025a46 100644 --- a/src/components/run/ColapsibleRow.tsx +++ b/src/components/run/ColapsibleRow.tsx @@ -3,6 +3,7 @@ import * as React from "react"; import TableRow from "@mui/material/TableRow"; import TableCell from "@mui/material/TableCell"; import { Box, Collapse, IconButton, Typography, Chip, TextField } from "@mui/material"; +import { Button } from "@mui/material"; import { DeleteForever, KeyboardArrowDown, KeyboardArrowUp, Settings } from "@mui/icons-material"; import { deleteRunFromStorage } from "../../api/storage"; import { columns, Data } from "./RunsTable"; @@ -11,6 +12,7 @@ import { GenericModal } from "../ui/GenericModal"; import { modalStyle } from "../recorder/AddWhereCondModal"; import { getUserById } from "../../api/auth"; import { useTranslation } from "react-i18next"; +import { useTheme } from "@mui/material/styles"; interface RunTypeChipProps { runByUserId?: string; @@ -39,6 +41,8 @@ interface CollapsibleRowProps { } export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, currentLog, abortRunHandler, runningRecordingName, urlRunId }: CollapsibleRowProps) => { const { t } = useTranslation(); + const theme = useTheme(); + const [isDeleteOpen, setDeleteOpen] = useState(false); const [openSettingsModal, setOpenSettingsModal] = useState(false); const [userEmail, setUserEmail] = useState(null); const runByLabel = row.runByScheduleId @@ -83,6 +87,17 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, cu fetchUserEmail(); }, [row.runByUserId]); + const handleConfirmDelete = async () => { + try { + const res = await deleteRunFromStorage(`${row.runId}`); + if (res) { + handleDelete(); + } + } finally { + setDeleteOpen(false); + } + }; + return ( *': { borderBottom: 'unset' } }} hover role="checkbox" tabIndex={-1} key={row.id}> @@ -120,13 +135,7 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, cu case 'delete': return ( - { - deleteRunFromStorage(`${row.runId}`).then((result: boolean) => { - if (result) { - handleDelete(); - } - }) - }}> + setDeleteOpen(true)}> @@ -192,6 +201,32 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, onToggleExpanded, cu + + setDeleteOpen(false)} modalStyle={{ ...modalStyle, padding: 0, backgroundColor: 'transparent', width: 'auto', maxWidth: '520px' }}> + + + {t('runs_table.delete_confirm.title', { + name: row.name, + defaultValue: 'Delete run "{{name}}"?' + })} + + + {t('runs_table.delete_confirm.message', { + name: row.name, + defaultValue: 'Are you sure you want to delete the run "{{name}}"?' + })} + + + + + + + ); }