@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import Tabs from '@mui/material/Tabs';
|
||||
import Tab from '@mui/material/Tab';
|
||||
import Box from '@mui/material/Box';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Paper, Button, useTheme } from "@mui/material";
|
||||
import { AutoAwesome, FormatListBulleted, VpnKey, Usb, Article, CloudQueue, Code, } from "@mui/icons-material";
|
||||
import { apiUrl } from "../../apiConfig";
|
||||
@@ -13,11 +14,13 @@ interface MainMenuProps {
|
||||
handleChangeContent: (newValue: string) => void;
|
||||
}
|
||||
|
||||
export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenuProps) => {
|
||||
export const MainMenu = ({ value = 'robots', handleChangeContent }: MainMenuProps) => {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleChange = (event: React.SyntheticEvent, newValue: string) => {
|
||||
navigate(`/${newValue}`);
|
||||
handleChangeContent(newValue);
|
||||
};
|
||||
|
||||
@@ -65,7 +68,7 @@ export const MainMenu = ({ value = 'recordings', handleChangeContent }: MainMenu
|
||||
textAlign: 'left',
|
||||
fontSize: 'medium',
|
||||
}}
|
||||
value="recordings"
|
||||
value="robots"
|
||||
label={t('mainmenu.recordings')}
|
||||
icon={<AutoAwesome />}
|
||||
iconPosition="start"
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState } from "react";
|
||||
import { RecordingsTable } from "./RecordingsTable";
|
||||
import { Grid } from "@mui/material";
|
||||
import { RunSettings, RunSettingsModal } from "../run/RunSettings";
|
||||
import { ScheduleSettings, ScheduleSettingsModal } from "./ScheduleSettings";
|
||||
import { IntegrationSettings, IntegrationSettingsModal } from "../integration/IntegrationSettings";
|
||||
import { RobotSettings, RobotSettingsModal } from "./RobotSettings";
|
||||
import { RobotEditModal } from './RobotEdit';
|
||||
import { RobotDuplicationModal } from './RobotDuplicate';
|
||||
import { RobotEditModal } from "./RobotEdit";
|
||||
import { RobotDuplicationModal } from "./RobotDuplicate";
|
||||
import { useNavigate, useLocation, useParams } from "react-router-dom";
|
||||
|
||||
interface RecordingsProps {
|
||||
handleEditRecording: (id: string, fileName: string) => void;
|
||||
@@ -15,181 +16,115 @@ interface RecordingsProps {
|
||||
setRecordingInfo: (id: string, name: string) => void;
|
||||
}
|
||||
|
||||
export const Recordings = ({ handleEditRecording, handleRunRecording, setRecordingInfo, handleScheduleRecording }: RecordingsProps) => {
|
||||
const [runSettingsAreOpen, setRunSettingsAreOpen] = useState(false);
|
||||
const [scheduleSettingsAreOpen, setScheduleSettingsAreOpen] = useState(false);
|
||||
const [integrateSettingsAreOpen, setIntegrateSettingsAreOpen] = useState(false);
|
||||
const [robotSettingsAreOpen, setRobotSettingsAreOpen] = useState(false);
|
||||
const [robotEditAreOpen, setRobotEditAreOpen] = useState(false);
|
||||
const [robotDuplicateAreOpen, setRobotDuplicateAreOpen] = useState(false);
|
||||
export const Recordings = ({
|
||||
handleEditRecording,
|
||||
handleRunRecording,
|
||||
setRecordingInfo,
|
||||
handleScheduleRecording,
|
||||
}: RecordingsProps) => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const { selectedRecordingId } = useParams();
|
||||
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 handleDuplicateRobot = (id: string, settings: RobotSettings) => { };
|
||||
|
||||
const handleSettingsAndIntegrate = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
setIntegrateSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
} else {
|
||||
setParams(params);
|
||||
setIntegrateSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
}
|
||||
}
|
||||
|
||||
const handleSettingsAndRun = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
setRunSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
} else {
|
||||
setParams(params);
|
||||
setRunSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
}
|
||||
}
|
||||
|
||||
const handleSettingsAndSchedule = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
setScheduleSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
} else {
|
||||
setParams(params);
|
||||
setScheduleSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
}
|
||||
}
|
||||
|
||||
const handleRobotSettings = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
setRobotSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
} else {
|
||||
setParams(params);
|
||||
setRobotSettingsAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
}
|
||||
}
|
||||
|
||||
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 handleDuplicateRobotOption = (id: string, name: string, params: string[]) => {
|
||||
if (params.length === 0) {
|
||||
setRobotDuplicateAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
} else {
|
||||
setParams(params);
|
||||
setRobotDuplicateAreOpen(true);
|
||||
setRecordingInfo(id, name);
|
||||
setSelectedRecordingId(id);
|
||||
}
|
||||
}
|
||||
const handleNavigate = (path: string, id: string, name: string, params: string[]) => {
|
||||
setParams(params);
|
||||
setRecordingInfo(id, name);
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setParams([]);
|
||||
setRunSettingsAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
setRecordingInfo("", "");
|
||||
navigate("/robots"); // Navigate back to the main robots page
|
||||
};
|
||||
|
||||
const handleIntegrateClose = () => {
|
||||
setParams([]);
|
||||
setIntegrateSettingsAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
// Determine which modal to open based on the current route
|
||||
const getCurrentModal = () => {
|
||||
const currentPath = location.pathname;
|
||||
|
||||
const handleScheduleClose = () => {
|
||||
setParams([]);
|
||||
setScheduleSettingsAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
|
||||
const handleRobotSettingsClose = () => {
|
||||
setParams([]);
|
||||
setRobotSettingsAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
|
||||
const handleRobotEditClose = () => {
|
||||
setParams([]);
|
||||
setRobotEditAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
|
||||
const handleRobotDuplicateClose = () => {
|
||||
setParams([]);
|
||||
setRobotDuplicateAreOpen(false);
|
||||
setRecordingInfo('', '');
|
||||
setSelectedRecordingId('');
|
||||
}
|
||||
if (currentPath.endsWith("/run")) {
|
||||
return (
|
||||
<RunSettingsModal
|
||||
isOpen={true}
|
||||
handleClose={handleClose}
|
||||
handleStart={handleRunRecording}
|
||||
isTask={params.length !== 0}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
} else if (currentPath.endsWith("/schedule")) {
|
||||
return (
|
||||
<ScheduleSettingsModal
|
||||
isOpen={true}
|
||||
handleClose={handleClose}
|
||||
handleStart={handleScheduleRecording}
|
||||
/>
|
||||
);
|
||||
} else if (currentPath.endsWith("/integrate")) {
|
||||
return (
|
||||
<IntegrationSettingsModal
|
||||
isOpen={true}
|
||||
handleClose={handleClose}
|
||||
handleStart={() => {}}
|
||||
/>
|
||||
);
|
||||
} else if (currentPath.endsWith("/settings")) {
|
||||
return (
|
||||
<RobotSettingsModal
|
||||
isOpen={true}
|
||||
handleClose={handleClose}
|
||||
handleStart={() => {}}
|
||||
/>
|
||||
);
|
||||
} else if (currentPath.endsWith("/edit")) {
|
||||
return (
|
||||
<RobotEditModal
|
||||
isOpen={true}
|
||||
handleClose={handleClose}
|
||||
handleStart={() => {}}
|
||||
/>
|
||||
);
|
||||
} else if (currentPath.endsWith("/duplicate")) {
|
||||
return (
|
||||
<RobotDuplicationModal
|
||||
isOpen={true}
|
||||
handleClose={handleClose}
|
||||
handleStart={() => {}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<RunSettingsModal isOpen={runSettingsAreOpen}
|
||||
handleClose={handleClose}
|
||||
handleStart={(settings) => handleRunRecording(settings)}
|
||||
isTask={params.length !== 0}
|
||||
params={params}
|
||||
/>
|
||||
<ScheduleSettingsModal isOpen={scheduleSettingsAreOpen}
|
||||
handleClose={handleScheduleClose}
|
||||
handleStart={(settings) => handleScheduleRecording(settings)}
|
||||
/>
|
||||
<IntegrationSettingsModal isOpen={integrateSettingsAreOpen}
|
||||
handleClose={handleIntegrateClose}
|
||||
handleStart={(settings) => handleIntegrateRecording(selectedRecordingId, settings)}
|
||||
/>
|
||||
<RobotSettingsModal isOpen={robotSettingsAreOpen}
|
||||
handleClose={handleRobotSettingsClose}
|
||||
handleStart={(settings) => handleSettingsRecording(selectedRecordingId, settings)}
|
||||
/>
|
||||
<RobotEditModal isOpen={robotEditAreOpen}
|
||||
handleClose={handleRobotEditClose}
|
||||
handleStart={(settings) => handleEditRobot(selectedRecordingId, settings)}
|
||||
/>
|
||||
<RobotDuplicationModal isOpen={robotDuplicateAreOpen}
|
||||
handleClose={handleRobotDuplicateClose}
|
||||
handleStart={(settings) => handleDuplicateRobot(selectedRecordingId, settings)}
|
||||
/>
|
||||
<Grid container direction="column" sx={{ padding: '30px' }}>
|
||||
{getCurrentModal()}
|
||||
<Grid container direction="column" sx={{ padding: "30px" }}>
|
||||
<Grid item xs>
|
||||
<RecordingsTable
|
||||
handleEditRecording={handleEditRecording}
|
||||
handleRunRecording={handleSettingsAndRun}
|
||||
handleScheduleRecording={handleSettingsAndSchedule}
|
||||
handleIntegrateRecording={handleSettingsAndIntegrate}
|
||||
handleSettingsRecording={handleRobotSettings}
|
||||
handleEditRobot={handleEditRobotOption}
|
||||
handleDuplicateRobot={handleDuplicateRobotOption}
|
||||
handleRunRecording={(id, name, params) =>
|
||||
handleNavigate(`/robots/${id}/run`, id, name, params)
|
||||
}
|
||||
handleScheduleRecording={(id, name, params) =>
|
||||
handleNavigate(`/robots/${id}/schedule`, id, name, params)
|
||||
}
|
||||
handleIntegrateRecording={(id, name, params) =>
|
||||
handleNavigate(`/robots/${id}/integrate`, id, name, params)
|
||||
}
|
||||
handleSettingsRecording={(id, name, params) =>
|
||||
handleNavigate(`/robots/${id}/settings`, id, name, params)
|
||||
}
|
||||
handleEditRobot={(id, name, params) =>
|
||||
handleNavigate(`/robots/${id}/edit`, id, name, params)
|
||||
}
|
||||
handleDuplicateRobot={(id, name, params) =>
|
||||
handleNavigate(`/robots/${id}/duplicate`, id, name, params)
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ import { GenericModal } from "../ui/GenericModal";
|
||||
import { modalStyle } from "../recorder/AddWhereCondModal";
|
||||
import { getUserById } from "../../api/auth";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
interface RunTypeChipProps {
|
||||
runByUserId?: string;
|
||||
@@ -37,6 +38,7 @@ interface CollapsibleRowProps {
|
||||
}
|
||||
export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRunHandler, runningRecordingName }: CollapsibleRowProps) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [open, setOpen] = useState(isOpen);
|
||||
const [openSettingsModal, setOpenSettingsModal] = useState(false);
|
||||
const [userEmail, setUserEmail] = useState<string | null>(null);
|
||||
@@ -47,7 +49,7 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRun
|
||||
: row.runByAPI
|
||||
? 'API'
|
||||
: 'Unknown';
|
||||
|
||||
|
||||
const logEndRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const scrollToLogBottom = () => {
|
||||
@@ -60,9 +62,20 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRun
|
||||
abortRunHandler();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
scrollToLogBottom();
|
||||
}, [currentLog])
|
||||
const handleRowExpand = () => {
|
||||
const newOpen = !open;
|
||||
setOpen(newOpen);
|
||||
if (newOpen) {
|
||||
navigate(`/runs/${row.robotMetaId}/run/${row.runId}`);
|
||||
} else {
|
||||
navigate(`/runs/${row.robotMetaId}`);
|
||||
}
|
||||
//scrollToLogBottom();
|
||||
};
|
||||
|
||||
// useEffect(() => {
|
||||
// scrollToLogBottom();
|
||||
// }, [currentLog])
|
||||
|
||||
useEffect(() => {
|
||||
const fetchUserEmail = async () => {
|
||||
@@ -83,10 +96,7 @@ export const CollapsibleRow = ({ row, handleDelete, isOpen, currentLog, abortRun
|
||||
<IconButton
|
||||
aria-label="expand row"
|
||||
size="small"
|
||||
onClick={() => {
|
||||
setOpen(!open);
|
||||
scrollToLogBottom();
|
||||
}}
|
||||
onClick={handleRowExpand}
|
||||
>
|
||||
{open ? <KeyboardArrowUp /> : <KeyboardArrowDown />}
|
||||
</IconButton>
|
||||
|
||||
@@ -12,7 +12,7 @@ import TableRow from '@mui/material/TableRow';
|
||||
import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField } from '@mui/material';
|
||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useGlobalInfoStore } from "../../context/globalInfo";
|
||||
import { getStoredRuns } from "../../api/storage";
|
||||
import { RunSettings } from "./RunSettings";
|
||||
@@ -68,6 +68,7 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
||||
runningRecordingName
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Update column labels using translation if needed
|
||||
const translatedColumns = columns.map(column => ({
|
||||
@@ -82,6 +83,14 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
||||
|
||||
const { notify, rerenderRuns, setRerenderRuns } = useGlobalInfoStore();
|
||||
|
||||
const handleAccordionChange = (robotMetaId: string, isExpanded: boolean) => {
|
||||
if (isExpanded) {
|
||||
navigate(`/runs/${robotMetaId}`);
|
||||
} else {
|
||||
navigate(`/runs`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChangePage = (event: unknown, newPage: number) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
@@ -155,7 +164,7 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
||||
</Box>
|
||||
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden' }}>
|
||||
{Object.entries(groupedRows).map(([id, data]) => (
|
||||
<Accordion key={id}>
|
||||
<Accordion key={id} onChange={(event, isExpanded) => handleAccordionChange(id, isExpanded)}>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
<Typography variant="h6">{data[data.length - 1].name}</Typography>
|
||||
</AccordionSummary>
|
||||
|
||||
@@ -18,6 +18,7 @@ import { apiUrl } from "../apiConfig";
|
||||
|
||||
interface MainPageProps {
|
||||
handleEditRecording: (id: string, fileName: string) => void;
|
||||
initialContent: string;
|
||||
}
|
||||
|
||||
export interface CreateRunResponse {
|
||||
@@ -30,9 +31,9 @@ export interface ScheduleRunResponse {
|
||||
runId: string;
|
||||
}
|
||||
|
||||
export const MainPage = ({ handleEditRecording }: MainPageProps) => {
|
||||
export const MainPage = ({ handleEditRecording, initialContent }: MainPageProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [content, setContent] = React.useState('recordings');
|
||||
const [content, setContent] = React.useState(initialContent);
|
||||
const [sockets, setSockets] = React.useState<Socket[]>([]);
|
||||
const [runningRecordingId, setRunningRecordingId] = React.useState('');
|
||||
const [runningRecordingName, setRunningRecordingName] = React.useState('');
|
||||
@@ -123,7 +124,7 @@ export const MainPage = ({ handleEditRecording }: MainPageProps) => {
|
||||
|
||||
const DisplayContent = () => {
|
||||
switch (content) {
|
||||
case 'recordings':
|
||||
case 'robots':
|
||||
return <Recordings
|
||||
handleEditRecording={handleEditRecording}
|
||||
handleRunRecording={handleRunRecording}
|
||||
|
||||
@@ -11,8 +11,8 @@ import { AlertSnackbar } from "../components/ui/AlertSnackbar";
|
||||
import Login from './Login';
|
||||
import Register from './Register';
|
||||
import UserRoute from '../routes/userRoute';
|
||||
import { Routes, Route, useNavigate } from 'react-router-dom';
|
||||
import { AppBar } from '@mui/material';
|
||||
import { Routes, Route, useNavigate, Navigate } from 'react-router-dom';
|
||||
import { Runs } from '../components/run/Runs';
|
||||
|
||||
export const PageWrapper = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -51,12 +51,14 @@ export const PageWrapper = () => {
|
||||
<AuthProvider>
|
||||
<SocketProvider>
|
||||
<React.Fragment>
|
||||
|
||||
{!browserId && <NavBar recordingName={recordingName} isRecording={!!browserId} />}
|
||||
|
||||
<Routes>
|
||||
<Route element={<UserRoute />}>
|
||||
<Route path="/" element={<MainPage handleEditRecording={handleEditRecording} />} />
|
||||
<Route path="/" element={<Navigate to="/robots" replace />} />
|
||||
<Route path="/robots/*" element={<MainPage handleEditRecording={handleEditRecording} initialContent="robots" />} />
|
||||
<Route path="/runs/*" element={<MainPage handleEditRecording={handleEditRecording} initialContent="runs" />} />
|
||||
<Route path="/proxy" element={<MainPage handleEditRecording={handleEditRecording} initialContent="proxy" />} />
|
||||
<Route path="/apikey" element={<MainPage handleEditRecording={handleEditRecording} initialContent="apikey" />} />
|
||||
</Route>
|
||||
<Route element={<UserRoute />}>
|
||||
<Route path="/recording" element={
|
||||
|
||||
Reference in New Issue
Block a user