Merge pull request #358 from getmaxun/improve-ui
feat(ui): runs & robots loader
This commit is contained in:
@@ -11,7 +11,7 @@ import TableRow from '@mui/material/TableRow';
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { WorkflowFile } from "maxun-core";
|
import { WorkflowFile } from "maxun-core";
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText } from "@mui/material";
|
import { IconButton, Button, Box, Typography, TextField, MenuItem, Menu, ListItemIcon, ListItemText, CircularProgress } from "@mui/material";
|
||||||
import { Schedule, DeleteForever, Edit, PlayCircle, Settings, Power, ContentCopy, MoreHoriz } from "@mui/icons-material";
|
import { Schedule, DeleteForever, Edit, PlayCircle, Settings, Power, ContentCopy, MoreHoriz } from "@mui/icons-material";
|
||||||
import { useGlobalInfoStore } from "../../context/globalInfo";
|
import { useGlobalInfoStore } from "../../context/globalInfo";
|
||||||
import { checkRunsForRecording, deleteRecordingFromStorage, getStoredRecordings } from "../../api/storage";
|
import { checkRunsForRecording, deleteRecordingFromStorage, getStoredRecordings } from "../../api/storage";
|
||||||
@@ -200,101 +200,107 @@ export const RecordingsTable = ({ handleEditRecording, handleRunRecording, handl
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden', marginTop: '15px' }}>
|
{rows.length === 0 ? (
|
||||||
<Table stickyHeader aria-label="sticky table">
|
<Box display="flex" justifyContent="center" alignItems="center" height="50%">
|
||||||
<TableHead>
|
<CircularProgress />
|
||||||
<TableRow>
|
</Box>
|
||||||
{columns.map((column) => (
|
) : (
|
||||||
<TableCell
|
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden', marginTop: '15px' }}>
|
||||||
key={column.id}
|
<Table stickyHeader aria-label="sticky table">
|
||||||
align={column.align}
|
<TableHead>
|
||||||
style={{ minWidth: column.minWidth }}
|
<TableRow>
|
||||||
>
|
{columns.map((column) => (
|
||||||
{column.label}
|
<TableCell
|
||||||
</TableCell>
|
key={column.id}
|
||||||
))}
|
align={column.align}
|
||||||
</TableRow>
|
style={{ minWidth: column.minWidth }}
|
||||||
</TableHead>
|
>
|
||||||
<TableBody>
|
{column.label}
|
||||||
{filteredRows.length !== 0 ? filteredRows
|
</TableCell>
|
||||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
))}
|
||||||
.map((row) => {
|
</TableRow>
|
||||||
return (
|
</TableHead>
|
||||||
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
|
<TableBody>
|
||||||
{columns.map((column) => {
|
{filteredRows.length !== 0 ? filteredRows
|
||||||
// @ts-ignore
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
const value: any = row[column.id];
|
.map((row) => {
|
||||||
if (value !== undefined) {
|
return (
|
||||||
return (
|
<TableRow hover role="checkbox" tabIndex={-1} key={row.id}>
|
||||||
<TableCell key={column.id} align={column.align}>
|
{columns.map((column) => {
|
||||||
{value}
|
// @ts-ignore
|
||||||
</TableCell>
|
const value: any = row[column.id];
|
||||||
);
|
if (value !== undefined) {
|
||||||
} else {
|
return (
|
||||||
switch (column.id) {
|
<TableCell key={column.id} align={column.align}>
|
||||||
case 'interpret':
|
{value}
|
||||||
return (
|
</TableCell>
|
||||||
<TableCell key={column.id} align={column.align}>
|
);
|
||||||
<InterpretButton handleInterpret={() => handleRunRecording(row.id, row.name, row.params || [])} />
|
} else {
|
||||||
</TableCell>
|
switch (column.id) {
|
||||||
);
|
case 'interpret':
|
||||||
case 'schedule':
|
return (
|
||||||
return (
|
<TableCell key={column.id} align={column.align}>
|
||||||
<TableCell key={column.id} align={column.align}>
|
<InterpretButton handleInterpret={() => handleRunRecording(row.id, row.name, row.params || [])} />
|
||||||
<ScheduleButton handleSchedule={() => handleScheduleRecording(row.id, row.name, row.params || [])} />
|
</TableCell>
|
||||||
</TableCell>
|
);
|
||||||
);
|
case 'schedule':
|
||||||
case 'integrate':
|
return (
|
||||||
return (
|
<TableCell key={column.id} align={column.align}>
|
||||||
<TableCell key={column.id} align={column.align}>
|
<ScheduleButton handleSchedule={() => handleScheduleRecording(row.id, row.name, row.params || [])} />
|
||||||
<IntegrateButton handleIntegrate={() => handleIntegrateRecording(row.id, row.name, row.params || [])} />
|
</TableCell>
|
||||||
</TableCell>
|
);
|
||||||
);
|
case 'integrate':
|
||||||
case 'options':
|
return (
|
||||||
return (
|
<TableCell key={column.id} align={column.align}>
|
||||||
<TableCell key={column.id} align={column.align}>
|
<IntegrateButton handleIntegrate={() => handleIntegrateRecording(row.id, row.name, row.params || [])} />
|
||||||
<OptionsButton
|
</TableCell>
|
||||||
handleEdit={() => handleEditRobot(row.id, row.name, row.params || [])}
|
);
|
||||||
handleDuplicate={() => {
|
case 'options':
|
||||||
handleDuplicateRobot(row.id, row.name, row.params || []);
|
return (
|
||||||
}}
|
<TableCell key={column.id} align={column.align}>
|
||||||
handleDelete={() => {
|
<OptionsButton
|
||||||
|
handleEdit={() => handleEditRobot(row.id, row.name, row.params || [])}
|
||||||
|
handleDuplicate={() => {
|
||||||
|
handleDuplicateRobot(row.id, row.name, row.params || []);
|
||||||
|
}}
|
||||||
|
handleDelete={() => {
|
||||||
|
|
||||||
checkRunsForRecording(row.id).then((result: boolean) => {
|
checkRunsForRecording(row.id).then((result: boolean) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
notify('warning', t('recordingtable.notifications.delete_warning'));
|
notify('warning', t('recordingtable.notifications.delete_warning'));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
deleteRecordingFromStorage(row.id).then((result: boolean) => {
|
deleteRecordingFromStorage(row.id).then((result: boolean) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
setRows([]);
|
setRows([]);
|
||||||
notify('success', t('recordingtable.notifications.delete_success'));
|
notify('success', t('recordingtable.notifications.delete_success'));
|
||||||
fetchRecordings();
|
fetchRecordings();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
);
|
);
|
||||||
case 'settings':
|
case 'settings':
|
||||||
return (
|
return (
|
||||||
<TableCell key={column.id} align={column.align}>
|
<TableCell key={column.id} align={column.align}>
|
||||||
<SettingsButton handleSettings={() => handleSettingsRecording(row.id, row.name, row.params || [])} />
|
<SettingsButton handleSettings={() => handleSettingsRecording(row.id, row.name, row.params || [])} />
|
||||||
</TableCell>
|
</TableCell>
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})}
|
||||||
})}
|
</TableRow>
|
||||||
</TableRow>
|
);
|
||||||
);
|
})
|
||||||
})
|
: null}
|
||||||
: null}
|
</TableBody>
|
||||||
</TableBody>
|
</Table>
|
||||||
</Table>
|
</TableContainer>
|
||||||
</TableContainer>
|
)}
|
||||||
<TablePagination
|
<TablePagination
|
||||||
rowsPerPageOptions={[10, 25, 50]}
|
rowsPerPageOptions={[10, 25, 50]}
|
||||||
component="div"
|
component="div"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import TableContainer from '@mui/material/TableContainer';
|
|||||||
import TableHead from '@mui/material/TableHead';
|
import TableHead from '@mui/material/TableHead';
|
||||||
import TablePagination from '@mui/material/TablePagination';
|
import TablePagination from '@mui/material/TablePagination';
|
||||||
import TableRow from '@mui/material/TableRow';
|
import TableRow from '@mui/material/TableRow';
|
||||||
import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField } from '@mui/material';
|
import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField, CircularProgress } from '@mui/material';
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
@@ -18,7 +18,6 @@ import { getStoredRuns } from "../../api/storage";
|
|||||||
import { RunSettings } from "./RunSettings";
|
import { RunSettings } from "./RunSettings";
|
||||||
import { CollapsibleRow } from "./ColapsibleRow";
|
import { CollapsibleRow } from "./ColapsibleRow";
|
||||||
|
|
||||||
// Export columns before the component
|
|
||||||
export const columns: readonly Column[] = [
|
export const columns: readonly Column[] = [
|
||||||
{ id: 'runStatus', label: 'Status', minWidth: 80 },
|
{ id: 'runStatus', label: 'Status', minWidth: 80 },
|
||||||
{ id: 'name', label: 'Name', minWidth: 80 },
|
{ id: 'name', label: 'Name', minWidth: 80 },
|
||||||
@@ -70,7 +69,6 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
// Update column labels using translation if needed
|
|
||||||
const translatedColumns = columns.map(column => ({
|
const translatedColumns = columns.map(column => ({
|
||||||
...column,
|
...column,
|
||||||
label: t(`runstable.${column.id}`, column.label)
|
label: t(`runstable.${column.id}`, column.label)
|
||||||
@@ -162,48 +160,54 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
sx={{ width: '250px' }}
|
sx={{ width: '250px' }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden' }}>
|
{rows.length === 0 ? (
|
||||||
{Object.entries(groupedRows).map(([id, data]) => (
|
<Box display="flex" justifyContent="center" alignItems="center" height="50%">
|
||||||
<Accordion key={id} onChange={(event, isExpanded) => handleAccordionChange(id, isExpanded)}>
|
<CircularProgress />
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
</Box>
|
||||||
<Typography variant="h6">{data[data.length - 1].name}</Typography>
|
) : (
|
||||||
</AccordionSummary>
|
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden' }}>
|
||||||
<AccordionDetails>
|
{Object.entries(groupedRows).map(([id, data]) => (
|
||||||
<Table stickyHeader aria-label="sticky table">
|
<Accordion key={id} onChange={(event, isExpanded) => handleAccordionChange(id, isExpanded)}>
|
||||||
<TableHead>
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
<TableRow>
|
<Typography variant="h6">{data[data.length - 1].name}</Typography>
|
||||||
<TableCell />
|
</AccordionSummary>
|
||||||
{translatedColumns.map((column) => (
|
<AccordionDetails>
|
||||||
<TableCell
|
<Table stickyHeader aria-label="sticky table">
|
||||||
key={column.id}
|
<TableHead>
|
||||||
align={column.align}
|
<TableRow>
|
||||||
style={{ minWidth: column.minWidth }}
|
<TableCell />
|
||||||
>
|
{translatedColumns.map((column) => (
|
||||||
{column.label}
|
<TableCell
|
||||||
</TableCell>
|
key={column.id}
|
||||||
))}
|
align={column.align}
|
||||||
</TableRow>
|
style={{ minWidth: column.minWidth }}
|
||||||
</TableHead>
|
>
|
||||||
<TableBody>
|
{column.label}
|
||||||
{data
|
</TableCell>
|
||||||
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
))}
|
||||||
.map((row) => (
|
</TableRow>
|
||||||
<CollapsibleRow
|
</TableHead>
|
||||||
row={row}
|
<TableBody>
|
||||||
handleDelete={handleDelete}
|
{data
|
||||||
key={`row-${row.id}`}
|
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||||
isOpen={runId === row.runId && runningRecordingName === row.name}
|
.map((row) => (
|
||||||
currentLog={currentInterpretationLog}
|
<CollapsibleRow
|
||||||
abortRunHandler={abortRunHandler}
|
row={row}
|
||||||
runningRecordingName={runningRecordingName}
|
handleDelete={handleDelete}
|
||||||
/>
|
key={`row-${row.id}`}
|
||||||
))}
|
isOpen={runId === row.runId && runningRecordingName === row.name}
|
||||||
</TableBody>
|
currentLog={currentInterpretationLog}
|
||||||
</Table>
|
abortRunHandler={abortRunHandler}
|
||||||
</AccordionDetails>
|
runningRecordingName={runningRecordingName}
|
||||||
</Accordion>
|
/>
|
||||||
))}
|
))}
|
||||||
</TableContainer>
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
))}
|
||||||
|
</TableContainer>
|
||||||
|
)}
|
||||||
<TablePagination
|
<TablePagination
|
||||||
rowsPerPageOptions={[10, 25, 50]}
|
rowsPerPageOptions={[10, 25, 50]}
|
||||||
component="div"
|
component="div"
|
||||||
|
|||||||
Reference in New Issue
Block a user