import * as React from 'react'; import SwipeableDrawer from '@mui/material/SwipeableDrawer'; import Typography from '@mui/material/Typography'; import { Button, TextField, Grid } from '@mui/material'; import { useCallback, useEffect, useRef, useState } from "react"; import { useSocketStore } from "../../context/socket"; import { Buffer } from 'buffer'; import { useBrowserDimensionsStore } from "../../context/browserDimensions"; import Table from '@mui/material/Table'; import TableBody from '@mui/material/TableBody'; import TableCell from '@mui/material/TableCell'; import TableContainer from '@mui/material/TableContainer'; import TableHead from '@mui/material/TableHead'; import TableRow from '@mui/material/TableRow'; import Paper from '@mui/material/Paper'; import StorageIcon from '@mui/icons-material/Storage'; import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; import { SidePanelHeader } from './SidePanelHeader'; import { useGlobalInfoStore } from '../../context/globalInfo'; import { useThemeMode } from '../../context/theme-provider'; import { useTranslation } from 'react-i18next'; interface InterpretationLogProps { isOpen: boolean; setIsOpen: (isOpen: boolean) => void; } export const InterpretationLog: React.FC = ({ isOpen, setIsOpen }) => { const { t } = useTranslation(); const [log, setLog] = useState(''); const [customValue, setCustomValue] = useState(''); const [tableData, setTableData] = useState([]); const [binaryData, setBinaryData] = useState(null); const logEndRef = useRef(null); const { width } = useBrowserDimensionsStore(); const { socket } = useSocketStore(); const { currentWorkflowActionsState, shouldResetInterpretationLog, notify } = useGlobalInfoStore(); const toggleDrawer = (newOpen: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => { if ( event.type === 'keydown' && ((event as React.KeyboardEvent).key === 'Tab' || (event as React.KeyboardEvent).key === 'Shift') ) { return; } setIsOpen(newOpen); }; const scrollLogToBottom = () => { if (logEndRef.current) { logEndRef.current.scrollIntoView({ behavior: "smooth" }); } }; const handleLog = useCallback((msg: string, date: boolean = true) => { if (!date) { setLog((prevState) => prevState + '\n' + msg); } else { setLog((prevState) => prevState + '\n' + `[${new Date().toLocaleString()}] ` + msg); } scrollLogToBottom(); }, [log, scrollLogToBottom]); const handleSerializableCallback = useCallback((data: any) => { setLog((prevState) => prevState + '\n' + t('interpretation_log.data_sections.serializable_received') + '\n' + JSON.stringify(data, null, 2) + '\n' + t('interpretation_log.data_sections.separator')); if (Array.isArray(data)) { setTableData(data); } scrollLogToBottom(); }, [log, scrollLogToBottom, t]); const handleBinaryCallback = useCallback(({ data, mimetype }: any) => { const base64String = Buffer.from(data).toString('base64'); const imageSrc = `data:${mimetype};base64,${base64String}`; setLog((prevState) => prevState + '\n' + t('interpretation_log.data_sections.binary_received') + '\n' + t('interpretation_log.data_sections.mimetype') + mimetype + '\n' + t('interpretation_log.data_sections.image_below') + '\n' + t('interpretation_log.data_sections.separator')); setBinaryData(imageSrc); scrollLogToBottom(); }, [log, scrollLogToBottom, t]); const handleCustomValueChange = (event: React.ChangeEvent) => { setCustomValue(event.target.value); }; useEffect(() => { if (shouldResetInterpretationLog) { setLog(''); setTableData([]); setBinaryData(null); } }, [shouldResetInterpretationLog]); useEffect(() => { socket?.on('log', handleLog); socket?.on('serializableCallback', handleSerializableCallback); socket?.on('binaryCallback', handleBinaryCallback); return () => { socket?.off('log', handleLog); socket?.off('serializableCallback', handleSerializableCallback); socket?.off('binaryCallback', handleBinaryCallback); }; }, [socket, handleLog, handleSerializableCallback, handleBinaryCallback]); // Extract columns dynamically from the first item of tableData const columns = tableData.length > 0 ? Object.keys(tableData[0]) : []; const { hasScrapeListAction, hasScreenshotAction, hasScrapeSchemaAction } = currentWorkflowActionsState useEffect(() => { if (hasScrapeListAction || hasScrapeSchemaAction || hasScreenshotAction) { setIsOpen(true); } }, [hasScrapeListAction, hasScrapeSchemaAction, hasScreenshotAction, setIsOpen]); const isDarkMode = useThemeMode(); return ( {t('interpretation_log.titles.output_preview')}
{ binaryData ? (
{t('interpretation_log.titles.screenshot')} {t('interpretation_log.titles.screenshot')}
) : tableData.length > 0 ? ( <> {columns.map((column) => ( {column} ))} {tableData.slice(0, Math.min(5, tableData.length)).map((row, index) => ( {columns.map((column) => ( {row[column]} ))} ))}
{t('interpretation_log.messages.additional_rows')} ) : ( {hasScrapeListAction || hasScrapeSchemaAction || hasScreenshotAction ? ( <> {t('interpretation_log.messages.successful_training')} ) : ( {t('interpretation_log.messages.no_selection')} )} )}
); };