diff --git a/public/locales/de.json b/public/locales/de.json index 58d90cffe..2e24c82b1 100644 --- a/public/locales/de.json +++ b/public/locales/de.json @@ -48,6 +48,12 @@ "options": "Optionen", "heading": "Meine Roboter", "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": { "title": "Geben Sie die URL ein", "login_title": "Ist für diese Website eine Anmeldung erforderlich?", @@ -90,6 +96,11 @@ "settings": "Einstellungen", "search": "Ausführungen suchen...", "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": { "no_runs": "Keine Ausführungen gefunden. Bitte versuchen Sie es erneut.", "delete_success": "Ausführung erfolgreich gelöscht" diff --git a/public/locales/en.json b/public/locales/en.json index f900089f4..ab84b92d7 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -48,6 +48,12 @@ "options": "Options", "heading":"My Robots", "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":{ "title":"Enter the URL", "login_title": "Does this website require logging in?", @@ -90,6 +96,11 @@ "settings":"Settings", "search":"Search Runs...", "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": { "no_runs": "No runs found. Please try again.", "delete_success": "Run deleted successfully" diff --git a/public/locales/es.json b/public/locales/es.json index 880f3be93..9072f6e90 100644 --- a/public/locales/es.json +++ b/public/locales/es.json @@ -48,6 +48,12 @@ "options": "Opciones", "heading": "Mis Robots", "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": { "title": "Ingresa la URL", "login_title": "¿Este sitio web requiere iniciar sesión?", @@ -90,6 +96,11 @@ "settings": "Ajustes", "search": "Buscar ejecuciones...", "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": { "no_runs": "No se encontraron ejecuciones. Por favor, inténtelo de nuevo.", "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" } }, - "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": { "buttons": { "preview": "Obtener Vista Previa de Datos de Salida", diff --git a/public/locales/ja.json b/public/locales/ja.json index 05071e8a9..68cfd8478 100644 --- a/public/locales/ja.json +++ b/public/locales/ja.json @@ -48,6 +48,12 @@ "options": "オプション", "heading": "私のロボット", "new": "ロボットを作成", + "search_criteria": "検索条件を調整してみてください", + "placeholder": { + "title": "始める準備ができました", + "body": "作成したロボットはここに表示されます。「ロボットを作成」をクリックして始めましょう!", + "search": "検索に一致するロボットはありません" + }, "modal": { "title": "URLを入力してください", "login_title": "このサイトはログインが必要ですか?", @@ -90,6 +96,11 @@ "settings": "設定", "search": "実行を検索...", "sort_tooltip": "クリックして並べ替え", + "placeholder": { + "title": "実行が見つかりません", + "body": "すべてのロボットの実行はここに表示されます。ロボットがアクティブになると、その実行はここに記録されます。", + "search": "検索に一致する実行はありません" + }, "notifications": { "no_runs": "実行が見つかりません。もう一度お試しください。", "delete_success": "実行が正常に削除されました" diff --git a/public/locales/tr.json b/public/locales/tr.json index db2f9ffd3..c63704e61 100644 --- a/public/locales/tr.json +++ b/public/locales/tr.json @@ -48,6 +48,12 @@ "options": "Seçenekler", "heading": "Robotlarım", "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": { "title": "URL’yi Girin", "login_title": "Bu web sitesine giriş gerekiyor mu?", @@ -90,6 +96,11 @@ "settings": "Ayarlar", "search": "Çalıştırma Ara...", "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": { "no_runs": "Çalıştırma bulunamadı. Lütfen tekrar deneyin.", "delete_success": "Çalıştırma başarıyla silindi" diff --git a/public/locales/zh.json b/public/locales/zh.json index abd5de9ff..ff83b560f 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -48,6 +48,12 @@ "options": "选项", "heading": "我的机器人", "new": "创建机器人", + "search_criteria": "请尝试调整您的搜索条件", + "placeholder": { + "title": "一切就绪,可以开始了", + "body": "您创建的机器人将显示在这里。点击“创建机器人”即可开始!", + "search": "没有与您搜索匹配的机器人" + }, "modal": { "title": "输入URL", "login_title": "此网站需要登录吗?", @@ -90,6 +96,11 @@ "settings": "设置", "search": "搜索运行记录...", "sort_tooltip": "点击排序", + "placeholder": { + "title": "未找到运行记录", + "body": "您所有的机器人运行记录都将显示在此处。一旦机器人被激活,其运行记录将在这里记下。", + "search": "没有与您搜索匹配的运行记录" + }, "notifications": { "no_runs": "未找到运行记录。请重试。", "delete_success": "运行记录删除成功" diff --git a/src/components/robot/RecordingsTable.tsx b/src/components/robot/RecordingsTable.tsx index 6ea86f746..8e294464a 100644 --- a/src/components/robot/RecordingsTable.tsx +++ b/src/components/robot/RecordingsTable.tsx @@ -23,6 +23,7 @@ import { ListItemText, FormControlLabel, Checkbox, + CircularProgress, } from "@mui/material"; import { Schedule, @@ -154,6 +155,7 @@ export const RecordingsTable = ({ const [searchTerm, setSearchTerm] = React.useState(''); const [isWarningModalOpen, setWarningModalOpen] = React.useState(false); const [activeBrowserId, setActiveBrowserId] = React.useState(''); + const [isLoading, setIsLoading] = React.useState(true); const columns = useMemo(() => [ { id: 'interpret', label: t('recordingtable.run'), minWidth: 80 }, @@ -270,6 +272,8 @@ export const RecordingsTable = ({ } catch (error) { console.error('Error fetching recordings:', error); notify('error', t('recordingtable.notifications.fetch_error')); + } finally { + setIsLoading(false); } }, [setRecordings, notify, t]); @@ -405,9 +409,7 @@ export const RecordingsTable = ({ } useEffect(() => { - if (rows.length === 0) { - fetchRecordings(); - } + fetchRecordings(); }, [fetchRecordings]); useEffect(() => { @@ -513,42 +515,81 @@ export const RecordingsTable = ({ - - - - - {columns.map((column) => ( - - {column.label} - - ))} - - - - {visibleRows.map((row) => ( - - ))} - -
-
- - + + {isLoading ? ( + + + + ) : filteredRows.length === 0 ? ( + + + {debouncedSearchTerm ? t('recordingtable.placeholder.search') : t('recordingtable.placeholder.title')} + + + {debouncedSearchTerm + ? t('recordingtable.search_criteria') + : t('recordingtable.placeholder.body') + } + + + ) : ( + <> + + + + + {columns.map((column) => ( + + {column.label} + + ))} + + + + {visibleRows.map((row) => ( + + ))} + +
+
+ + + + )} setWarningModalOpen(false)} modalStyle={modalStyle}>
{t('recordingtable.warning_modal.title')} diff --git a/src/components/run/RunsTable.tsx b/src/components/run/RunsTable.tsx index 2628bdda0..12b2c84b2 100644 --- a/src/components/run/RunsTable.tsx +++ b/src/components/run/RunsTable.tsx @@ -9,7 +9,7 @@ import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TablePagination from '@mui/material/TablePagination'; 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 SearchIcon from '@mui/icons-material/Search'; import { useLocation, useNavigate } from 'react-router-dom'; @@ -134,6 +134,7 @@ export const RunsTable: React.FC = ({ const [rows, setRows] = useState([]); const [searchTerm, setSearchTerm] = useState(''); + const [isLoading, setIsLoading] = useState(true); const [paginationStates, setPaginationStates] = useState({}); @@ -224,6 +225,8 @@ export const RunsTable: React.FC = ({ } } catch (error) { notify('error', t('runstable.notifications.fetch_error')); + } finally { + setIsLoading(false); } }, [notify, t]); @@ -231,6 +234,7 @@ export const RunsTable: React.FC = ({ let mounted = true; if (rows.length === 0 || rerenderRuns) { + setIsLoading(true); fetchRuns().then(() => { if (mounted) { setRerenderRuns(false); @@ -378,102 +382,140 @@ export const RunsTable: React.FC = ({ /> - - {Object.entries(groupedRows) - .slice( - accordionPage * accordionsPerPage, - accordionPage * accordionsPerPage + accordionsPerPage - ) - .map(([robotMetaId, data]) => ( - handleAccordionChange(robotMetaId, isExpanded)} - TransitionProps={{ unmountOnExit: true }} // Optimize accordion rendering - > - }> - {data[0].name} - - - - - - - {translatedColumns.map((column) => ( - { - if (column.id === 'startedAt' || column.id === 'finishedAt') { - handleSort(column.id, robotMetaId); - } - }} - > - - + + + ) : Object.keys(groupedRows).length === 0 ? ( + + + {searchTerm ? t('runstable.placeholder.search') : t('runstable.placeholder.title')} + + + {searchTerm + ? t('recordingtable.search_criteria') + : t('runstable.placeholder.body') + } + + + ) : ( + <> + + {Object.entries(groupedRows) + .slice( + accordionPage * accordionsPerPage, + accordionPage * accordionsPerPage + accordionsPerPage + ) + .map(([robotMetaId, data]) => ( + handleAccordionChange(robotMetaId, isExpanded)} + TransitionProps={{ unmountOnExit: true }} // Optimize accordion rendering + > + }> + {data[0].name} + + +
+ + + + {translatedColumns.map((column) => ( + { + if (column.id === 'startedAt' || column.id === 'finishedAt') { + handleSort(column.id, robotMetaId); + } + }} + > + - {column.label} - - {renderSortIcon(column, robotMetaId)} - - - - - ))} - - - - {renderTableRows(data, robotMetaId)} - -
- - handleChangePage(robotMetaId, newPage)} - onRowsPerPageChange={(event) => - handleChangeRowsPerPage(robotMetaId, +event.target.value) - } - rowsPerPageOptions={[10, 25, 50, 100]} - /> -
-
- ))} -
- - + > + + {column.label} + + {renderSortIcon(column, robotMetaId)} + + + + + ))} + + + + {renderTableRows(data, robotMetaId)} + + + + handleChangePage(robotMetaId, newPage)} + onRowsPerPageChange={(event) => + handleChangeRowsPerPage(robotMetaId, +event.target.value) + } + rowsPerPageOptions={[10, 25, 50, 100]} + /> + + + ))} + + + + + )} ); }; \ No newline at end of file