Merge pull request #761 from RohitR311/norob-ui
feat: placeholder message for empty robots and runs
This commit is contained in:
@@ -48,6 +48,12 @@
|
|||||||
"options": "Optionen",
|
"options": "Optionen",
|
||||||
"heading": "Meine Roboter",
|
"heading": "Meine Roboter",
|
||||||
"new": "Roboter erstellen",
|
"new": "Roboter erstellen",
|
||||||
|
"search_criteria": "Versuchen Sie, Ihre Suchkriterien anzupassen",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "Alles bereit für den Start",
|
||||||
|
"body": "Roboter, die Sie erstellen, werden hier angezeigt. Klicken Sie auf „Roboter erstellen“, um loszulegen!",
|
||||||
|
"search": "Keine Roboter entsprechen Ihrer Suche"
|
||||||
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"title": "Geben Sie die URL ein",
|
"title": "Geben Sie die URL ein",
|
||||||
"login_title": "Ist für diese Website eine Anmeldung erforderlich?",
|
"login_title": "Ist für diese Website eine Anmeldung erforderlich?",
|
||||||
@@ -90,6 +96,11 @@
|
|||||||
"settings": "Einstellungen",
|
"settings": "Einstellungen",
|
||||||
"search": "Ausführungen suchen...",
|
"search": "Ausführungen suchen...",
|
||||||
"sort_tooltip": "Zum Sortieren klicken",
|
"sort_tooltip": "Zum Sortieren klicken",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "Keine Durchläufe gefunden",
|
||||||
|
"body": "Hier werden alle Ihre Roboter-Durchläufe angezeigt. Sobald ein Roboter aktiv ist, werden seine Durchläufe hier protokolliert.",
|
||||||
|
"search": "Keine Durchläufe entsprechen Ihrer Suche"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"no_runs": "Keine Ausführungen gefunden. Bitte versuchen Sie es erneut.",
|
"no_runs": "Keine Ausführungen gefunden. Bitte versuchen Sie es erneut.",
|
||||||
"delete_success": "Ausführung erfolgreich gelöscht"
|
"delete_success": "Ausführung erfolgreich gelöscht"
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
"options": "Options",
|
"options": "Options",
|
||||||
"heading":"My Robots",
|
"heading":"My Robots",
|
||||||
"new":"Create Robot",
|
"new":"Create Robot",
|
||||||
|
"search_criteria": "Try adjusting your search criteria",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "You're All Set to Start",
|
||||||
|
"body": "Robots you create will appear here. Click \"Create Robot\" to get started!",
|
||||||
|
"search": "No robots match your search"
|
||||||
|
},
|
||||||
"modal":{
|
"modal":{
|
||||||
"title":"Enter the URL",
|
"title":"Enter the URL",
|
||||||
"login_title": "Does this website require logging in?",
|
"login_title": "Does this website require logging in?",
|
||||||
@@ -90,6 +96,11 @@
|
|||||||
"settings":"Settings",
|
"settings":"Settings",
|
||||||
"search":"Search Runs...",
|
"search":"Search Runs...",
|
||||||
"sort_tooltip": "Click to sort",
|
"sort_tooltip": "Click to sort",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "No Runs Found",
|
||||||
|
"body": "This is where all your robot runs will appear. Once a robot is active, its runs will be logged here.",
|
||||||
|
"search":"No runs match your search"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"no_runs": "No runs found. Please try again.",
|
"no_runs": "No runs found. Please try again.",
|
||||||
"delete_success": "Run deleted successfully"
|
"delete_success": "Run deleted successfully"
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
"options": "Opciones",
|
"options": "Opciones",
|
||||||
"heading": "Mis Robots",
|
"heading": "Mis Robots",
|
||||||
"new": "Crear Robot",
|
"new": "Crear Robot",
|
||||||
|
"search_criteria": "Intente ajustar sus criterios de búsqueda",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "Todo listo para empezar",
|
||||||
|
"body": "Los robots que cree aparecerán aquí. ¡Haga clic en \"Crear robot\" para comenzar!",
|
||||||
|
"search": "Ningún robot coincide con su búsqueda"
|
||||||
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"title": "Ingresa la URL",
|
"title": "Ingresa la URL",
|
||||||
"login_title": "¿Este sitio web requiere iniciar sesión?",
|
"login_title": "¿Este sitio web requiere iniciar sesión?",
|
||||||
@@ -90,6 +96,11 @@
|
|||||||
"settings": "Ajustes",
|
"settings": "Ajustes",
|
||||||
"search": "Buscar ejecuciones...",
|
"search": "Buscar ejecuciones...",
|
||||||
"sort_tooltip": "Haga clic para ordenar",
|
"sort_tooltip": "Haga clic para ordenar",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "No se encontraron ejecuciones",
|
||||||
|
"body": "Aquí aparecerán todas las ejecuciones de sus robots. Una vez que un robot esté activo, sus ejecuciones se registrarán aquí.",
|
||||||
|
"search": "Ninguna ejecución coincide con su búsqueda"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"no_runs": "No se encontraron ejecuciones. Por favor, inténtelo de nuevo.",
|
"no_runs": "No se encontraron ejecuciones. Por favor, inténtelo de nuevo.",
|
||||||
"delete_success": "Ejecución eliminada con éxito"
|
"delete_success": "Ejecución eliminada con éxito"
|
||||||
@@ -276,24 +287,6 @@
|
|||||||
"reset_successful": "Se reiniciaron correctamente todas las capturas y se volvió al estado inicial"
|
"reset_successful": "Se reiniciaron correctamente todas las capturas y se volvió al estado inicial"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interpretation_log": {
|
|
||||||
"titles": {
|
|
||||||
"output_preview": "Vista Previa de Datos de Salida",
|
|
||||||
"screenshot": "Captura de pantalla"
|
|
||||||
},
|
|
||||||
"messages": {
|
|
||||||
"additional_rows": "Se extraerán filas adicionales de datos una vez que termine la grabación.",
|
|
||||||
"successful_training": "¡Has entrenado exitosamente al robot para realizar acciones! Haz clic en el botón de abajo para obtener una vista previa de los datos que tu robot extraerá.",
|
|
||||||
"no_selection": "Parece que aún no has seleccionado nada para extraer. Una vez que lo hagas, el robot mostrará una vista previa de tus selecciones aquí."
|
|
||||||
},
|
|
||||||
"data_sections": {
|
|
||||||
"binary_received": "---------- Datos binarios de salida recibidos ----------",
|
|
||||||
"serializable_received": "---------- Datos serializables de salida recibidos ----------",
|
|
||||||
"mimetype": "tipo MIME: ",
|
|
||||||
"image_below": "La imagen se muestra a continuación:",
|
|
||||||
"separator": "--------------------------------------------------"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"interpretation_buttons": {
|
"interpretation_buttons": {
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"preview": "Obtener Vista Previa de Datos de Salida",
|
"preview": "Obtener Vista Previa de Datos de Salida",
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
"options": "オプション",
|
"options": "オプション",
|
||||||
"heading": "私のロボット",
|
"heading": "私のロボット",
|
||||||
"new": "ロボットを作成",
|
"new": "ロボットを作成",
|
||||||
|
"search_criteria": "検索条件を調整してみてください",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "始める準備ができました",
|
||||||
|
"body": "作成したロボットはここに表示されます。「ロボットを作成」をクリックして始めましょう!",
|
||||||
|
"search": "検索に一致するロボットはありません"
|
||||||
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"title": "URLを入力してください",
|
"title": "URLを入力してください",
|
||||||
"login_title": "このサイトはログインが必要ですか?",
|
"login_title": "このサイトはログインが必要ですか?",
|
||||||
@@ -90,6 +96,11 @@
|
|||||||
"settings": "設定",
|
"settings": "設定",
|
||||||
"search": "実行を検索...",
|
"search": "実行を検索...",
|
||||||
"sort_tooltip": "クリックして並べ替え",
|
"sort_tooltip": "クリックして並べ替え",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "実行が見つかりません",
|
||||||
|
"body": "すべてのロボットの実行はここに表示されます。ロボットがアクティブになると、その実行はここに記録されます。",
|
||||||
|
"search": "検索に一致する実行はありません"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"no_runs": "実行が見つかりません。もう一度お試しください。",
|
"no_runs": "実行が見つかりません。もう一度お試しください。",
|
||||||
"delete_success": "実行が正常に削除されました"
|
"delete_success": "実行が正常に削除されました"
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
"options": "Seçenekler",
|
"options": "Seçenekler",
|
||||||
"heading": "Robotlarım",
|
"heading": "Robotlarım",
|
||||||
"new": "Robot Oluştur",
|
"new": "Robot Oluştur",
|
||||||
|
"search_criteria": "Arama kriterlerinizi değiştirmeyi deneyin",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "Başlamaya Hazırsınız",
|
||||||
|
"body": "Oluşturduğunuz robotlar burada görünecektir. Başlamak için \"Robot Oluştur\"a tıklayın!",
|
||||||
|
"search": "Aramanızla eşleşen robot yok"
|
||||||
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"title": "URL’yi Girin",
|
"title": "URL’yi Girin",
|
||||||
"login_title": "Bu web sitesine giriş gerekiyor mu?",
|
"login_title": "Bu web sitesine giriş gerekiyor mu?",
|
||||||
@@ -90,6 +96,11 @@
|
|||||||
"settings": "Ayarlar",
|
"settings": "Ayarlar",
|
||||||
"search": "Çalıştırma Ara...",
|
"search": "Çalıştırma Ara...",
|
||||||
"sort_tooltip": "Sıralamak için tıkla",
|
"sort_tooltip": "Sıralamak için tıkla",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "Çalıştırma Bulunamadı",
|
||||||
|
"body": "Tüm robot çalıştırmalarınız burada görünecektir. Bir robot aktif olduğunda, çalıştırmaları buraya kaydedilecektir.",
|
||||||
|
"search": "Aramanızla eşleşen çalıştırma yok"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"no_runs": "Çalıştırma bulunamadı. Lütfen tekrar deneyin.",
|
"no_runs": "Çalıştırma bulunamadı. Lütfen tekrar deneyin.",
|
||||||
"delete_success": "Çalıştırma başarıyla silindi"
|
"delete_success": "Çalıştırma başarıyla silindi"
|
||||||
|
|||||||
@@ -48,6 +48,12 @@
|
|||||||
"options": "选项",
|
"options": "选项",
|
||||||
"heading": "我的机器人",
|
"heading": "我的机器人",
|
||||||
"new": "创建机器人",
|
"new": "创建机器人",
|
||||||
|
"search_criteria": "请尝试调整您的搜索条件",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "一切就绪,可以开始了",
|
||||||
|
"body": "您创建的机器人将显示在这里。点击“创建机器人”即可开始!",
|
||||||
|
"search": "没有与您搜索匹配的机器人"
|
||||||
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"title": "输入URL",
|
"title": "输入URL",
|
||||||
"login_title": "此网站需要登录吗?",
|
"login_title": "此网站需要登录吗?",
|
||||||
@@ -90,6 +96,11 @@
|
|||||||
"settings": "设置",
|
"settings": "设置",
|
||||||
"search": "搜索运行记录...",
|
"search": "搜索运行记录...",
|
||||||
"sort_tooltip": "点击排序",
|
"sort_tooltip": "点击排序",
|
||||||
|
"placeholder": {
|
||||||
|
"title": "未找到运行记录",
|
||||||
|
"body": "您所有的机器人运行记录都将显示在此处。一旦机器人被激活,其运行记录将在这里记下。",
|
||||||
|
"search": "没有与您搜索匹配的运行记录"
|
||||||
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"no_runs": "未找到运行记录。请重试。",
|
"no_runs": "未找到运行记录。请重试。",
|
||||||
"delete_success": "运行记录删除成功"
|
"delete_success": "运行记录删除成功"
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
ListItemText,
|
ListItemText,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
|
CircularProgress,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import {
|
import {
|
||||||
Schedule,
|
Schedule,
|
||||||
@@ -154,6 +155,7 @@ export const RecordingsTable = ({
|
|||||||
const [searchTerm, setSearchTerm] = React.useState('');
|
const [searchTerm, setSearchTerm] = React.useState('');
|
||||||
const [isWarningModalOpen, setWarningModalOpen] = React.useState(false);
|
const [isWarningModalOpen, setWarningModalOpen] = React.useState(false);
|
||||||
const [activeBrowserId, setActiveBrowserId] = React.useState('');
|
const [activeBrowserId, setActiveBrowserId] = React.useState('');
|
||||||
|
const [isLoading, setIsLoading] = React.useState(true);
|
||||||
|
|
||||||
const columns = useMemo(() => [
|
const columns = useMemo(() => [
|
||||||
{ id: 'interpret', label: t('recordingtable.run'), minWidth: 80 },
|
{ id: 'interpret', label: t('recordingtable.run'), minWidth: 80 },
|
||||||
@@ -270,6 +272,8 @@ export const RecordingsTable = ({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching recordings:', error);
|
console.error('Error fetching recordings:', error);
|
||||||
notify('error', t('recordingtable.notifications.fetch_error'));
|
notify('error', t('recordingtable.notifications.fetch_error'));
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [setRecordings, notify, t]);
|
}, [setRecordings, notify, t]);
|
||||||
|
|
||||||
@@ -405,9 +409,7 @@ export const RecordingsTable = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (rows.length === 0) {
|
fetchRecordings();
|
||||||
fetchRecordings();
|
|
||||||
}
|
|
||||||
}, [fetchRecordings]);
|
}, [fetchRecordings]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -513,42 +515,81 @@ export const RecordingsTable = ({
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden', marginTop: '15px' }}>
|
|
||||||
<Table stickyHeader aria-label="sticky table">
|
|
||||||
<TableHead>
|
|
||||||
<TableRow>
|
|
||||||
{columns.map((column) => (
|
|
||||||
<MemoizedTableCell
|
|
||||||
key={column.id}
|
|
||||||
style={{ minWidth: column.minWidth }}
|
|
||||||
>
|
|
||||||
{column.label}
|
|
||||||
</MemoizedTableCell>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{visibleRows.map((row) => (
|
|
||||||
<TableRowMemoized
|
|
||||||
key={row.id}
|
|
||||||
row={row}
|
|
||||||
columns={columns}
|
|
||||||
handlers={handlers}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
</TableContainer>
|
|
||||||
|
|
||||||
<TablePagination
|
{isLoading ? (
|
||||||
rowsPerPageOptions={[10, 25, 50, 100]}
|
<Box
|
||||||
component="div"
|
display="flex"
|
||||||
count={filteredRows.length}
|
justifyContent="center"
|
||||||
rowsPerPage={rowsPerPage}
|
alignItems="center"
|
||||||
page={page}
|
sx={{
|
||||||
onPageChange={handleChangePage}
|
minHeight: '60vh',
|
||||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
width: '100%'
|
||||||
/>
|
}}
|
||||||
|
>
|
||||||
|
<CircularProgress size={60} />
|
||||||
|
</Box>
|
||||||
|
) : filteredRows.length === 0 ? (
|
||||||
|
<Box
|
||||||
|
display="flex"
|
||||||
|
flexDirection="column"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent="center"
|
||||||
|
sx={{
|
||||||
|
minHeight: 300,
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'text.secondary'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6" gutterBottom>
|
||||||
|
{debouncedSearchTerm ? t('recordingtable.placeholder.search') : t('recordingtable.placeholder.title')}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2" color="text.secondary">
|
||||||
|
{debouncedSearchTerm
|
||||||
|
? t('recordingtable.search_criteria')
|
||||||
|
: t('recordingtable.placeholder.body')
|
||||||
|
}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden', marginTop: '15px' }}>
|
||||||
|
<Table stickyHeader aria-label="sticky table">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
{columns.map((column) => (
|
||||||
|
<MemoizedTableCell
|
||||||
|
key={column.id}
|
||||||
|
style={{ minWidth: column.minWidth }}
|
||||||
|
>
|
||||||
|
{column.label}
|
||||||
|
</MemoizedTableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{visibleRows.map((row) => (
|
||||||
|
<TableRowMemoized
|
||||||
|
key={row.id}
|
||||||
|
row={row}
|
||||||
|
columns={columns}
|
||||||
|
handlers={handlers}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={[10, 25, 50, 100]}
|
||||||
|
component="div"
|
||||||
|
count={filteredRows.length}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
page={page}
|
||||||
|
onPageChange={handleChangePage}
|
||||||
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<GenericModal isOpen={isWarningModalOpen} onClose={() => setWarningModalOpen(false)} modalStyle={modalStyle}>
|
<GenericModal isOpen={isWarningModalOpen} onClose={() => setWarningModalOpen(false)} modalStyle={modalStyle}>
|
||||||
<div style={{ padding: '10px' }}>
|
<div style={{ padding: '10px' }}>
|
||||||
<Typography variant="h6" gutterBottom>{t('recordingtable.warning_modal.title')}</Typography>
|
<Typography variant="h6" gutterBottom>{t('recordingtable.warning_modal.title')}</Typography>
|
||||||
|
|||||||
@@ -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, Tooltip } from '@mui/material';
|
import { Accordion, AccordionSummary, AccordionDetails, Typography, Box, TextField, Tooltip, 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 { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
@@ -134,6 +134,7 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
|
|
||||||
const [rows, setRows] = useState<Data[]>([]);
|
const [rows, setRows] = useState<Data[]>([]);
|
||||||
const [searchTerm, setSearchTerm] = useState('');
|
const [searchTerm, setSearchTerm] = useState('');
|
||||||
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
|
|
||||||
const [paginationStates, setPaginationStates] = useState<PaginationState>({});
|
const [paginationStates, setPaginationStates] = useState<PaginationState>({});
|
||||||
|
|
||||||
@@ -224,6 +225,8 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notify('error', t('runstable.notifications.fetch_error'));
|
notify('error', t('runstable.notifications.fetch_error'));
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
}, [notify, t]);
|
}, [notify, t]);
|
||||||
|
|
||||||
@@ -231,6 +234,7 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
|
||||||
if (rows.length === 0 || rerenderRuns) {
|
if (rows.length === 0 || rerenderRuns) {
|
||||||
|
setIsLoading(true);
|
||||||
fetchRuns().then(() => {
|
fetchRuns().then(() => {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setRerenderRuns(false);
|
setRerenderRuns(false);
|
||||||
@@ -378,102 +382,140 @@ export const RunsTable: React.FC<RunsTableProps> = ({
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden' }}>
|
{isLoading? (
|
||||||
{Object.entries(groupedRows)
|
<Box
|
||||||
.slice(
|
display="flex"
|
||||||
accordionPage * accordionsPerPage,
|
justifyContent="center"
|
||||||
accordionPage * accordionsPerPage + accordionsPerPage
|
alignItems="center"
|
||||||
)
|
sx={{
|
||||||
.map(([robotMetaId, data]) => (
|
minHeight: '60vh',
|
||||||
<Accordion
|
width: '100%'
|
||||||
key={robotMetaId}
|
}}
|
||||||
onChange={(event, isExpanded) => handleAccordionChange(robotMetaId, isExpanded)}
|
>
|
||||||
TransitionProps={{ unmountOnExit: true }} // Optimize accordion rendering
|
<CircularProgress size={60} />
|
||||||
>
|
</Box>
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
) : Object.keys(groupedRows).length === 0 ? (
|
||||||
<Typography variant="h6">{data[0].name}</Typography>
|
<Box
|
||||||
</AccordionSummary>
|
display="flex"
|
||||||
<AccordionDetails>
|
flexDirection="column"
|
||||||
<Table stickyHeader aria-label="sticky table">
|
alignItems="center"
|
||||||
<TableHead>
|
justifyContent="center"
|
||||||
<TableRow>
|
sx={{
|
||||||
<TableCell />
|
minHeight: 300,
|
||||||
{translatedColumns.map((column) => (
|
textAlign: 'center',
|
||||||
<TableCell
|
color: 'text.secondary'
|
||||||
key={column.id}
|
}}
|
||||||
align={column.align}
|
>
|
||||||
style={{
|
<Typography variant="h6" gutterBottom>
|
||||||
minWidth: column.minWidth,
|
{searchTerm ? t('runstable.placeholder.search') : t('runstable.placeholder.title')}
|
||||||
cursor: column.id === 'startedAt' || column.id === 'finishedAt' ? 'pointer' : 'default'
|
</Typography>
|
||||||
}}
|
<Typography variant="body2" color="text.secondary">
|
||||||
onClick={() => {
|
{searchTerm
|
||||||
if (column.id === 'startedAt' || column.id === 'finishedAt') {
|
? t('recordingtable.search_criteria')
|
||||||
handleSort(column.id, robotMetaId);
|
: t('runstable.placeholder.body')
|
||||||
}
|
}
|
||||||
}}
|
</Typography>
|
||||||
>
|
</Box>
|
||||||
<Tooltip
|
) : (
|
||||||
title={
|
<>
|
||||||
(column.id === 'startedAt' || column.id === 'finishedAt')
|
<TableContainer component={Paper} sx={{ width: '100%', overflow: 'hidden' }}>
|
||||||
? t('runstable.sort_tooltip')
|
{Object.entries(groupedRows)
|
||||||
: ''
|
.slice(
|
||||||
}
|
accordionPage * accordionsPerPage,
|
||||||
>
|
accordionPage * accordionsPerPage + accordionsPerPage
|
||||||
<Box sx={{
|
)
|
||||||
display: 'flex',
|
.map(([robotMetaId, data]) => (
|
||||||
alignItems: 'center',
|
<Accordion
|
||||||
gap: 1,
|
key={robotMetaId}
|
||||||
'&:hover': {
|
onChange={(event, isExpanded) => handleAccordionChange(robotMetaId, isExpanded)}
|
||||||
'& .sort-icon': {
|
TransitionProps={{ unmountOnExit: true }} // Optimize accordion rendering
|
||||||
opacity: 1
|
>
|
||||||
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
|
<Typography variant="h6">{data[0].name}</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<Table stickyHeader aria-label="sticky table">
|
||||||
|
<TableHead>
|
||||||
|
<TableRow>
|
||||||
|
<TableCell />
|
||||||
|
{translatedColumns.map((column) => (
|
||||||
|
<TableCell
|
||||||
|
key={column.id}
|
||||||
|
align={column.align}
|
||||||
|
style={{
|
||||||
|
minWidth: column.minWidth,
|
||||||
|
cursor: column.id === 'startedAt' || column.id === 'finishedAt' ? 'pointer' : 'default'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (column.id === 'startedAt' || column.id === 'finishedAt') {
|
||||||
|
handleSort(column.id, robotMetaId);
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}}>
|
>
|
||||||
{column.label}
|
<Tooltip
|
||||||
<Box className="sort-icon" sx={{
|
title={
|
||||||
display: 'flex',
|
(column.id === 'startedAt' || column.id === 'finishedAt')
|
||||||
alignItems: 'center',
|
? t('runstable.sort_tooltip')
|
||||||
opacity: accordionSortConfigs[robotMetaId]?.field === column.id ? 1 : 0.3,
|
: ''
|
||||||
transition: 'opacity 0.2s'
|
}
|
||||||
}}>
|
>
|
||||||
{renderSortIcon(column, robotMetaId)}
|
<Box sx={{
|
||||||
</Box>
|
display: 'flex',
|
||||||
</Box>
|
alignItems: 'center',
|
||||||
</Tooltip>
|
gap: 1,
|
||||||
</TableCell>
|
'&:hover': {
|
||||||
))}
|
'& .sort-icon': {
|
||||||
</TableRow>
|
opacity: 1
|
||||||
</TableHead>
|
}
|
||||||
<TableBody>
|
}
|
||||||
{renderTableRows(data, robotMetaId)}
|
}}>
|
||||||
</TableBody>
|
{column.label}
|
||||||
</Table>
|
<Box className="sort-icon" sx={{
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
opacity: accordionSortConfigs[robotMetaId]?.field === column.id ? 1 : 0.3,
|
||||||
|
transition: 'opacity 0.2s'
|
||||||
|
}}>
|
||||||
|
{renderSortIcon(column, robotMetaId)}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{renderTableRows(data, robotMetaId)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
|
||||||
<TablePagination
|
<TablePagination
|
||||||
component="div"
|
component="div"
|
||||||
count={data.length}
|
count={data.length}
|
||||||
rowsPerPage={getPaginationState(robotMetaId).rowsPerPage}
|
rowsPerPage={getPaginationState(robotMetaId).rowsPerPage}
|
||||||
page={getPaginationState(robotMetaId).page}
|
page={getPaginationState(robotMetaId).page}
|
||||||
onPageChange={(_, newPage) => handleChangePage(robotMetaId, newPage)}
|
onPageChange={(_, newPage) => handleChangePage(robotMetaId, newPage)}
|
||||||
onRowsPerPageChange={(event) =>
|
onRowsPerPageChange={(event) =>
|
||||||
handleChangeRowsPerPage(robotMetaId, +event.target.value)
|
handleChangeRowsPerPage(robotMetaId, +event.target.value)
|
||||||
}
|
}
|
||||||
rowsPerPageOptions={[10, 25, 50, 100]}
|
rowsPerPageOptions={[10, 25, 50, 100]}
|
||||||
/>
|
/>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
</Accordion>
|
</Accordion>
|
||||||
))}
|
))}
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
|
|
||||||
<TablePagination
|
<TablePagination
|
||||||
component="div"
|
component="div"
|
||||||
count={Object.keys(groupedRows).length}
|
count={Object.keys(groupedRows).length}
|
||||||
page={accordionPage}
|
page={accordionPage}
|
||||||
rowsPerPage={accordionsPerPage}
|
rowsPerPage={accordionsPerPage}
|
||||||
onPageChange={handleAccordionPageChange}
|
onPageChange={handleAccordionPageChange}
|
||||||
onRowsPerPageChange={handleAccordionsPerPageChange}
|
onRowsPerPageChange={handleAccordionsPerPageChange}
|
||||||
rowsPerPageOptions={[10, 25, 50, 100]}
|
rowsPerPageOptions={[10, 25, 50, 100]}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user