@@ -57,6 +57,95 @@ router.get('/recordings/:id', requireSignIn, async (req, res) => {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
/**
|
||||
* PUT endpoint to update the name and limit of a robot.
|
||||
*/
|
||||
router.put('/recordings/:id', requireSignIn, async (req: AuthenticatedRequest, res) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const { name, limit } = req.body;
|
||||
|
||||
// Validate input
|
||||
if (!name && limit === undefined) {
|
||||
return res.status(400).json({ error: 'Either "name" or "limit" must be provided.' });
|
||||
}
|
||||
|
||||
// Fetch the robot by ID
|
||||
const robot = await Robot.findOne({ where: { 'recording_meta.id': id } });
|
||||
|
||||
if (!robot) {
|
||||
return res.status(404).json({ error: 'Robot not found.' });
|
||||
}
|
||||
|
||||
// Update fields if provided
|
||||
if (name) {
|
||||
robot.set('recording_meta', { ...robot.recording_meta, name });
|
||||
}
|
||||
|
||||
// Update the limit
|
||||
if (limit !== undefined) {
|
||||
const workflow = [...robot.recording.workflow]; // Create a copy of the workflow
|
||||
|
||||
// Ensure the workflow structure is valid before updating
|
||||
if (
|
||||
workflow.length > 0 &&
|
||||
workflow[0]?.what?.[0]
|
||||
) {
|
||||
// Create a new workflow object with the updated limit
|
||||
const updatedWorkflow = workflow.map((step, index) => {
|
||||
if (index === 0) { // Assuming you want to update the first step
|
||||
return {
|
||||
...step,
|
||||
what: step.what.map((action, actionIndex) => {
|
||||
if (actionIndex === 0) { // Assuming the first action needs updating
|
||||
return {
|
||||
...action,
|
||||
args: (action.args ?? []).map((arg, argIndex) => {
|
||||
if (argIndex === 0) { // Assuming the first argument needs updating
|
||||
return { ...arg, limit };
|
||||
}
|
||||
return arg;
|
||||
}),
|
||||
};
|
||||
}
|
||||
return action;
|
||||
}),
|
||||
};
|
||||
}
|
||||
return step;
|
||||
});
|
||||
|
||||
// Replace the workflow in the recording object
|
||||
robot.set('recording', { ...robot.recording, workflow: updatedWorkflow });
|
||||
} else {
|
||||
return res.status(400).json({ error: 'Invalid workflow structure for updating limit.' });
|
||||
}
|
||||
}
|
||||
|
||||
await robot.save();
|
||||
|
||||
const updatedRobot = await Robot.findOne({ where: { 'recording_meta.id': id } });
|
||||
console.log('After save:', updatedRobot);
|
||||
|
||||
// Log the update
|
||||
logger.log('info', `Robot with ID ${id} was updated successfully.`);
|
||||
|
||||
return res.status(200).json({ message: 'Robot updated successfully', robot });
|
||||
} catch (error) {
|
||||
// Safely handle the error type
|
||||
if (error instanceof Error) {
|
||||
logger.log('error', `Error updating robot with ID ${req.params.id}: ${error.message}`);
|
||||
return res.status(500).json({ error: error.message });
|
||||
} else {
|
||||
logger.log('error', `Unknown error updating robot with ID ${req.params.id}`);
|
||||
return res.status(500).json({ error: 'An unknown error occurred.' });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* DELETE endpoint for deleting a recording from the storage.
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,20 @@ export const getStoredRecordings = async (): Promise<string[] | null> => {
|
||||
}
|
||||
};
|
||||
|
||||
export const updateRecording = async (id: string, data: { name?: string; limit?: number }): Promise<boolean> => {
|
||||
try {
|
||||
const response = await axios.put(`${apiUrl}/storage/recordings/${id}`, data);
|
||||
if (response.status === 200) {
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(`Couldn't update recording with id ${id}`);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error(`Error updating recording: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getStoredRuns = async (): Promise<string[] | null> => {
|
||||
try {
|
||||
const response = await axios.get(`${apiUrl}/storage/runs`);
|
||||
|
||||
@@ -9,8 +9,8 @@ import TablePagination from '@mui/material/TablePagination';
|
||||
import TableRow from '@mui/material/TableRow';
|
||||
import { useEffect } from "react";
|
||||
import { WorkflowFile } from "maxun-core";
|
||||
import { IconButton, Button, Box, Typography, TextField } from "@mui/material";
|
||||
import { Schedule, DeleteForever, Edit, PlayCircle, Settings, Power } from "@mui/icons-material";
|
||||
import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText } from "@mui/material";
|
||||
import { Schedule, DeleteForever, Edit, PlayCircle, Settings, Power, ContentCopy, } from "@mui/icons-material";
|
||||
import LinkIcon from '@mui/icons-material/Link';
|
||||
import { useGlobalInfoStore } from "../../context/globalInfo";
|
||||
import { deleteRecordingFromStorage, getStoredRecordings } from "../../api/storage";
|
||||
@@ -18,7 +18,7 @@ import { Add } from "@mui/icons-material";
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { stopRecording } from "../../api/recording";
|
||||
import { GenericModal } from '../atoms/GenericModal';
|
||||
|
||||
import { Menu as MenuIcon } from '@mui/icons-material';
|
||||
|
||||
/** TODO:
|
||||
* 1. allow editing existing robot after persisting browser steps
|
||||
@@ -26,7 +26,7 @@ import { GenericModal } from '../atoms/GenericModal';
|
||||
*/
|
||||
|
||||
interface Column {
|
||||
id: 'interpret' | 'name' | 'delete' | 'schedule' | 'integrate' | 'settings';
|
||||
id: 'interpret' | 'name' | 'options' | 'schedule' | 'integrate' | 'settings';
|
||||
label: string;
|
||||
minWidth?: number;
|
||||
align?: 'right';
|
||||
@@ -69,8 +69,8 @@ const columns: readonly Column[] = [
|
||||
minWidth: 80,
|
||||
},
|
||||
{
|
||||
id: 'delete',
|
||||
label: 'Delete',
|
||||
id: 'options',
|
||||
label: 'Options',
|
||||
minWidth: 80,
|
||||
},
|
||||
];
|
||||
@@ -90,9 +90,10 @@ interface RecordingsTableProps {
|
||||
handleScheduleRecording: (id: string, fileName: string, params: string[]) => void;
|
||||
handleIntegrateRecording: (id: string, fileName: string, params: string[]) => void;
|
||||
handleSettingsRecording: (id: string, fileName: string, params: string[]) => void;
|
||||
handleEditRobot: (id: string, name: string, params: string[]) => void;
|
||||
}
|
||||
|
||||
export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording }: RecordingsTableProps) => {
|
||||
export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handleScheduleRecording, handleIntegrateRecording, handleSettingsRecording, handleEditRobot }: RecordingsTableProps) => {
|
||||
const [page, setPage] = React.useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = React.useState(10);
|
||||
const [rows, setRows] = React.useState<Data[]>([]);
|
||||
@@ -248,22 +249,27 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl
|
||||
<IntegrateButton handleIntegrate={() => handleIntegrateRecording(row.id, row.name, row.params || [])} />
|
||||
</TableCell>
|
||||
);
|
||||
case 'delete':
|
||||
return (
|
||||
<TableCell key={column.id} align={column.align}>
|
||||
<IconButton aria-label="add" size="small" onClick={() => {
|
||||
deleteRecordingFromStorage(row.id).then((result: boolean) => {
|
||||
if (result) {
|
||||
setRows([]);
|
||||
notify('success', 'Recording deleted successfully');
|
||||
fetchRecordings();
|
||||
}
|
||||
})
|
||||
}}>
|
||||
<DeleteForever />
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
);
|
||||
case 'options':
|
||||
return (
|
||||
<TableCell key={column.id} align={column.align}>
|
||||
<OptionsButton
|
||||
handleEdit={() => handleEditRobot(row.id, row.name, row.params || [])}
|
||||
handleDelete={() => {
|
||||
deleteRecordingFromStorage(row.id).then((result: boolean) => {
|
||||
if (result) {
|
||||
setRows([]);
|
||||
notify('success', 'Recording deleted successfully');
|
||||
fetchRecordings();
|
||||
}
|
||||
})
|
||||
}}
|
||||
handleDuplicate={() => {
|
||||
notify('info', 'Duplicating recording...');
|
||||
// Implement duplication logic here
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
);
|
||||
case 'settings':
|
||||
return (
|
||||
<TableCell key={column.id} align={column.align}>
|
||||
@@ -377,6 +383,60 @@ const SettingsButton = ({ handleSettings }: SettingsButtonProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
interface OptionsButtonProps {
|
||||
handleEdit: () => void;
|
||||
handleDelete: () => void;
|
||||
handleDuplicate: () => void;
|
||||
}
|
||||
|
||||
const OptionsButton = ({ handleEdit, handleDelete, handleDuplicate }: OptionsButtonProps) => {
|
||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||
|
||||
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
aria-label="options"
|
||||
size="small"
|
||||
onClick={handleClick}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Menu
|
||||
anchorEl={anchorEl}
|
||||
open={Boolean(anchorEl)}
|
||||
onClose={handleClose}
|
||||
>
|
||||
<MenuItem onClick={() => { handleEdit(); handleClose(); }}>
|
||||
<ListItemIcon>
|
||||
<Edit fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>Edit</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => { handleDelete(); handleClose(); }}>
|
||||
<ListItemIcon>
|
||||
<DeleteForever fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>Delete</ListItemText>
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => { handleDuplicate(); handleClose(); }}>
|
||||
<ListItemIcon>
|
||||
<ContentCopy fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<ListItemText>Duplicate</ListItemText>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const modalStyle = {
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
|
||||
178
src/components/molecules/RobotEdit.tsx
Normal file
178
src/components/molecules/RobotEdit.tsx
Normal file
@@ -0,0 +1,178 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { GenericModal } from "../atoms/GenericModal";
|
||||
import { TextField, Typography, Box, Button } from "@mui/material";
|
||||
import { modalStyle } from "./AddWhereCondModal";
|
||||
import { useGlobalInfoStore } from '../../context/globalInfo';
|
||||
import { getStoredRecording, updateRecording } from '../../api/storage';
|
||||
import { WhereWhatPair } from 'maxun-core';
|
||||
|
||||
interface RobotMeta {
|
||||
name: string;
|
||||
id: string;
|
||||
createdAt: string;
|
||||
pairs: number;
|
||||
updatedAt: string;
|
||||
params: any[];
|
||||
}
|
||||
|
||||
interface RobotWorkflow {
|
||||
workflow: WhereWhatPair[];
|
||||
}
|
||||
|
||||
interface RobotEditOptions {
|
||||
name: string;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
interface ScheduleConfig {
|
||||
runEvery: number;
|
||||
runEveryUnit: 'MINUTES' | 'HOURS' | 'DAYS' | 'WEEKS' | 'MONTHS';
|
||||
startFrom: 'SUNDAY' | 'MONDAY' | 'TUESDAY' | 'WEDNESDAY' | 'THURSDAY' | 'FRIDAY' | 'SATURDAY';
|
||||
atTimeStart?: string;
|
||||
atTimeEnd?: string;
|
||||
timezone: string;
|
||||
lastRunAt?: Date;
|
||||
nextRunAt?: Date;
|
||||
cronExpression?: string;
|
||||
}
|
||||
|
||||
export interface RobotSettings {
|
||||
id: string;
|
||||
userId?: number;
|
||||
recording_meta: RobotMeta;
|
||||
recording: RobotWorkflow;
|
||||
google_sheet_email?: string | null;
|
||||
google_sheet_name?: string | null;
|
||||
google_sheet_id?: string | null;
|
||||
google_access_token?: string | null;
|
||||
google_refresh_token?: string | null;
|
||||
schedule?: ScheduleConfig | null;
|
||||
}
|
||||
|
||||
interface RobotSettingsProps {
|
||||
isOpen: boolean;
|
||||
handleStart: (settings: RobotSettings) => void;
|
||||
handleClose: () => void;
|
||||
initialSettings?: RobotSettings | null;
|
||||
|
||||
}
|
||||
|
||||
export const RobotEditModal = ({ isOpen, handleStart, handleClose, initialSettings }: RobotSettingsProps) => {
|
||||
const [robot, setRobot] = useState<RobotSettings | null>(null);
|
||||
const { recordingId, notify } = useGlobalInfoStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
getRobot();
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const getRobot = async () => {
|
||||
if (recordingId) {
|
||||
const robot = await getStoredRecording(recordingId);
|
||||
setRobot(robot);
|
||||
} else {
|
||||
notify('error', 'Could not find robot details. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
const handleRobotNameChange = (newName: string) => {
|
||||
setRobot((prev) =>
|
||||
prev ? { ...prev, recording_meta: { ...prev.recording_meta, name: newName } } : prev
|
||||
);
|
||||
};
|
||||
|
||||
const handleLimitChange = (newLimit: number) => {
|
||||
setRobot((prev) => {
|
||||
if (!prev) return prev;
|
||||
|
||||
const updatedWorkflow = [...prev.recording.workflow];
|
||||
|
||||
if (
|
||||
updatedWorkflow.length > 0 &&
|
||||
updatedWorkflow[0]?.what &&
|
||||
updatedWorkflow[0].what.length > 0 &&
|
||||
updatedWorkflow[0].what[0].args &&
|
||||
updatedWorkflow[0].what[0].args.length > 0 &&
|
||||
updatedWorkflow[0].what[0].args[0]
|
||||
) {
|
||||
updatedWorkflow[0].what[0].args[0].limit = newLimit;
|
||||
}
|
||||
|
||||
return { ...prev, recording: { ...prev.recording, workflow: updatedWorkflow } };
|
||||
});
|
||||
};
|
||||
const handleSave = async () => {
|
||||
if (!robot) return;
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
name: robot.recording_meta.name,
|
||||
limit: robot.recording.workflow[0]?.what[0]?.args?.[0]?.limit,
|
||||
};
|
||||
|
||||
const success = await updateRecording(robot.recording_meta.id, payload);
|
||||
|
||||
if (success) {
|
||||
notify('success', 'Robot updated successfully.');
|
||||
handleStart(robot); // Inform parent about the updated robot
|
||||
handleClose(); // Close the modal
|
||||
|
||||
window.location.reload();
|
||||
} else {
|
||||
notify('error', 'Failed to update the robot. Please try again.');
|
||||
}
|
||||
} catch (error) {
|
||||
notify('error', 'An error occurred while updating the robot.');
|
||||
console.error('Error updating robot:', error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<GenericModal
|
||||
isOpen={isOpen}
|
||||
onClose={handleClose}
|
||||
modalStyle={modalStyle}
|
||||
>
|
||||
<>
|
||||
<Typography variant="h5" style={{ marginBottom: '20px' }}>Edit Robot</Typography>
|
||||
<Box style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
{
|
||||
robot && (
|
||||
<>
|
||||
<TextField
|
||||
label="Change Robot Name"
|
||||
key="Change Robot Name"
|
||||
type='text'
|
||||
value={robot.recording_meta.name}
|
||||
onChange={(e) => handleRobotNameChange(e.target.value)}
|
||||
style={{ marginBottom: '20px' }}
|
||||
/>
|
||||
{robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== undefined && (
|
||||
<TextField
|
||||
label="Robot Limit"
|
||||
type="number"
|
||||
value={robot.recording.workflow[0].what[0].args[0].limit || ''}
|
||||
onChange={(e) =>
|
||||
handleLimitChange(parseInt(e.target.value, 10) || 0)
|
||||
}
|
||||
style={{ marginBottom: '20px' }}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Box mt={2} display="flex" justifyContent="flex-end" onClick={handleSave}>
|
||||
<Button variant="contained" color="primary">
|
||||
Save Changes
|
||||
</Button>
|
||||
<Button onClick={handleClose} color="primary" variant="outlined" style={{ marginLeft: '10px' }}>
|
||||
Cancel
|
||||
</Button>
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</Box>
|
||||
</>
|
||||
</GenericModal>
|
||||
);
|
||||
};
|
||||
@@ -45,6 +45,8 @@ export interface Data {
|
||||
// task: string;
|
||||
log: string;
|
||||
runId: string;
|
||||
robotId: string;
|
||||
robotMetaId: string;
|
||||
interpreterSettings: RunSettings;
|
||||
serializableOutput: any;
|
||||
binaryOutput: any;
|
||||
@@ -63,8 +65,6 @@ export const RunsTable = (
|
||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
||||
const [rows, setRows] = useState<Data[]>([]);
|
||||
|
||||
console.log(`rows runs: ${JSON.stringify(rows)}`);
|
||||
|
||||
const { notify, rerenderRuns, setRerenderRuns } = useGlobalInfoStore();
|
||||
|
||||
const handleChangePage = (event: unknown, newPage: number) => {
|
||||
@@ -105,12 +105,12 @@ export const RunsTable = (
|
||||
fetchRuns();
|
||||
};
|
||||
|
||||
// Group runs by recording name
|
||||
// Group runs by robot meta id
|
||||
const groupedRows = rows.reduce((acc, row) => {
|
||||
if (!acc[row.name]) {
|
||||
acc[row.name] = [];
|
||||
if (!acc[row.robotMetaId]) {
|
||||
acc[row.robotMetaId] = [];
|
||||
}
|
||||
acc[row.name].push(row);
|
||||
acc[row.robotMetaId].push(row);
|
||||
return acc;
|
||||
}, {} as Record<string, Data[]>);
|
||||
|
||||
@@ -120,10 +120,10 @@ export const RunsTable = (
|
||||
All Runs
|
||||
</Typography>
|
||||
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden' }}>
|
||||
{Object.entries(groupedRows).map(([name, group]) => (
|
||||
<Accordion key={name}>
|
||||
{Object.entries(groupedRows).map(([id, data]) => (
|
||||
<Accordion key={id}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography variant="h6">{name}</Typography>
|
||||
<Typography variant="h6">{data[data.length - 1].name}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<Table stickyHeader aria-label="sticky table">
|
||||
@@ -142,17 +142,19 @@ export const RunsTable = (
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{group.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => (
|
||||
<CollapsibleRow
|
||||
row={row}
|
||||
handleDelete={handleDelete}
|
||||
key={`row-${row.id}`}
|
||||
isOpen={runId === row.runId && runningRecordingName === row.name}
|
||||
currentLog={currentInterpretationLog}
|
||||
abortRunHandler={abortRunHandler}
|
||||
runningRecordingName={runningRecordingName}
|
||||
/>
|
||||
))}
|
||||
{data
|
||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||
.map((row) => (
|
||||
<CollapsibleRow
|
||||
row={row}
|
||||
handleDelete={handleDelete}
|
||||
key={`row-${row.id}`}
|
||||
isOpen={runId === row.runId && runningRecordingName === row.name}
|
||||
currentLog={currentInterpretationLog}
|
||||
abortRunHandler={abortRunHandler}
|
||||
runningRecordingName={runningRecordingName}
|
||||
/>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</AccordionDetails>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { RunSettings, RunSettingsModal } from "../molecules/RunSettings";
|
||||
import { ScheduleSettings, ScheduleSettingsModal } from "../molecules/ScheduleSettings";
|
||||
import { IntegrationSettings, IntegrationSettingsModal } from "../molecules/IntegrationSettings";
|
||||
import { RobotSettings, RobotSettingsModal } from "../molecules/RobotSettings";
|
||||
import { RobotEditModal } from '../molecules/RobotEdit';
|
||||
|
||||
interface RecordingsProps {
|
||||
handleEditRecording: (id: string, fileName: string) => void;
|
||||
@@ -18,10 +19,12 @@ export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordi
|
||||
const [scheduleSettingsAreOpen, setScheduleSettingsAreOpen] = useState(false);
|
||||
const [integrateSettingsAreOpen, setIntegrateSettingsAreOpen] = useState(false);
|
||||
const [robotSettingsAreOpen, setRobotSettingsAreOpen] = useState(false);
|
||||
const [robotEditAreOpen, setRobotEditAreOpen] = useState(false);
|
||||
const [params, setParams] = useState<string[]>([]);
|
||||
const [selectedRecordingId, setSelectedRecordingId] = useState<string>('');
|
||||
const handleIntegrateRecording = (id: string, settings: IntegrationSettings) => {};
|
||||
const handleSettingsRecording = (id: string, settings: RobotSettings) => {};
|
||||
const handleEditRobot = (id: string, settings: RobotSettings) => {};
|
||||
|
||||
const handleSettingsAndIntegrate = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
@@ -75,6 +78,19 @@ export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordi
|
||||
}
|
||||
}
|
||||
|
||||
const handleEditRobotOption = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
setRobotEditAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
} else {
|
||||
setParams(params);
|
||||
setRobotEditAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
}
|
||||
}
|
||||
|
||||
const handleClose = () => {
|
||||
setParams([]);
|
||||
setRunSettingsAreOpen(false);
|
||||
@@ -103,6 +119,13 @@ export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordi
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
|
||||
const handleRobotEditClose = () => {
|
||||
setParams([]);
|
||||
setRobotEditAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<RunSettingsModal isOpen={runSettingsAreOpen}
|
||||
@@ -123,6 +146,10 @@ export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordi
|
||||
handleClose={handleRobotSettingsClose}
|
||||
handleStart={(settings) => handleSettingsRecording(selectedRecordingId, settings)}
|
||||
/>
|
||||
<RobotEditModal isOpen={robotEditAreOpen}
|
||||
handleClose={handleRobotEditClose}
|
||||
handleStart={(settings) => handleEditRobot(selectedRecordingId,settings)}
|
||||
/>
|
||||
<Grid container direction="column" sx={{ padding: '30px' }}>
|
||||
<Grid item xs>
|
||||
<RecordingsTable
|
||||
@@ -131,6 +158,7 @@ export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordi
|
||||
handleScheduleRecording={handleSettingsAndSchedule}
|
||||
handleIntegrateRecording={handleSettingsAndIntegrate}
|
||||
handleSettingsRecording={handleRobotSettings}
|
||||
handleEditRobot={handleEditRobotOption}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user