Files
parcer/src/components/molecules/RunContent.tsx

246 lines
9.0 KiB
TypeScript
Raw Normal View History

2024-11-12 10:35:49 +05:30
import { Box, Tabs, Typography, Tab, Paper, Button } from "@mui/material";
2024-06-24 22:38:29 +05:30
import Highlight from "react-highlight";
import * as React from "react";
import { Data } from "./RunsTable";
import { TabPanel, TabContext } from "@mui/lab";
import ArticleIcon from '@mui/icons-material/Article';
2024-11-12 10:35:49 +05:30
import ImageIcon from '@mui/icons-material/Image';
2024-10-11 01:19:05 +05:30
import { useEffect, useState } from "react";
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';
2024-10-24 04:40:05 +05:30
import 'highlight.js/styles/github.css';
2024-12-21 17:41:53 +05:30
import { useTranslation } from "react-i18next";
2024-06-24 22:38:29 +05:30
interface RunContentProps {
row: Data,
currentLog: string,
interpretationInProgress: boolean,
logEndRef: React.RefObject<HTMLDivElement>,
abortRunHandler: () => void,
}
2024-09-27 23:40:01 +05:30
export const RunContent = ({ row, currentLog, interpretationInProgress, logEndRef, abortRunHandler }: RunContentProps) => {
2024-12-21 17:41:53 +05:30
const { t } = useTranslation();
2024-06-24 22:38:29 +05:30
const [tab, setTab] = React.useState<string>('log');
2024-10-11 01:19:05 +05:30
const [tableData, setTableData] = useState<any[]>([]);
const [columns, setColumns] = useState<string[]>([]);
2024-06-24 22:38:29 +05:30
useEffect(() => {
setTab(tab);
2024-11-12 10:35:49 +05:30
}, [interpretationInProgress]);
2024-06-24 22:38:29 +05:30
2024-11-20 05:14:34 +05:30
useEffect(() => {
if (row.serializableOutput && Object.keys(row.serializableOutput).length > 0) {
const firstKey = Object.keys(row.serializableOutput)[0];
const data = row.serializableOutput[firstKey];
if (Array.isArray(data)) {
// Filter out completely empty rows
const filteredData = data.filter(row =>
Object.values(row).some(value => value !== undefined && value !== "")
);
setTableData(filteredData);
if (filteredData.length > 0) {
setColumns(Object.keys(filteredData[0]));
}
2024-10-11 01:19:05 +05:30
}
}
2024-11-20 05:14:34 +05:30
}, [row.serializableOutput]);
2024-11-20 05:14:18 +05:30
2024-10-11 01:19:05 +05:30
2024-11-11 23:56:56 +05:30
// Function to convert table data to CSV format
const convertToCSV = (data: any[], columns: string[]): string => {
2024-11-12 10:35:49 +05:30
const header = columns.join(',');
const rows = data.map(row =>
2024-11-11 23:56:56 +05:30
columns.map(col => JSON.stringify(row[col], null, 2)).join(',')
2024-11-12 10:35:49 +05:30
);
return [header, ...rows].join('\n');
};
2024-11-11 23:56:56 +05:30
const downloadCSV = () => {
2024-11-12 10:35:49 +05:30
const csvContent = convertToCSV(tableData, columns);
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
2024-11-11 23:56:56 +05:30
const link = document.createElement("a");
link.href = url;
2024-11-12 10:35:49 +05:30
link.setAttribute("download", "data.csv");
2024-11-11 23:56:56 +05:30
document.body.appendChild(link);
2024-11-12 10:35:49 +05:30
link.click();
document.body.removeChild(link);
};
2024-11-11 23:56:56 +05:30
2024-06-24 22:38:29 +05:30
return (
<Box sx={{ width: '100%' }}>
<TabContext value={tab}>
2024-09-27 23:40:01 +05:30
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
2024-11-24 00:49:39 +05:30
<Tabs
2025-01-08 12:50:46 +05:30
value={tab}
onChange={(e, newTab) => setTab(newTab)}
aria-label="run-content-tabs"
sx={{
// Remove the default blue indicator
'& .MuiTabs-indicator': {
backgroundColor: '#FF00C3', // Change to pink
},
// Remove default transition effects
'& .MuiTab-root': {
'&.Mui-selected': {
color: '#FF00C3',
},
}
}}
>
<Tab
label={t('run_content.tabs.output_data')}
value='output'
sx={{
color: (theme) => theme.palette.mode === 'dark' ? '#fff' : '#000',
'&:hover': {
color: '#FF00C3'
},
'&.Mui-selected': {
color: '#FF00C3',
}
}}
/>
<Tab
label={t('run_content.tabs.log')}
value='log'
sx={{
color: (theme) => theme.palette.mode === 'dark' ? '#fff' : '#000',
'&:hover': {
color: '#FF00C3'
},
'&.Mui-selected': {
color: '#FF00C3',
}
}}
/>
</Tabs>
2024-06-24 22:38:29 +05:30
</Box>
2024-09-27 23:40:01 +05:30
<TabPanel value='log'>
<Box sx={{
margin: 1,
background: '#19171c',
overflowY: 'scroll',
overflowX: 'scroll',
width: '700px',
height: 'fit-content',
maxHeight: '450px',
}}>
<div>
<Highlight className="javascript">
{interpretationInProgress ? currentLog : row.log}
</Highlight>
<div style={{ float: "left", clear: "both" }}
ref={logEndRef} />
</div>
</Box>
{interpretationInProgress ? <Button
color="error"
onClick={abortRunHandler}
>
2024-12-21 17:41:53 +05:30
{t('run_content.buttons.stop')}
2024-09-27 23:40:01 +05:30
</Button> : null}
</TabPanel>
<TabPanel value='output' sx={{ width: '700px' }}>
{!row || !row.serializableOutput || !row.binaryOutput
|| (Object.keys(row.serializableOutput).length === 0 && Object.keys(row.binaryOutput).length === 0)
2024-12-21 17:41:53 +05:30
? <Typography>{t('run_content.empty_output')}</Typography> : null}
2024-06-24 22:38:29 +05:30
2024-09-27 23:40:01 +05:30
{row.serializableOutput &&
Object.keys(row.serializableOutput).length !== 0 &&
<div>
<Typography variant='h6' sx={{ display: 'flex', alignItems: 'center' }}>
<ArticleIcon sx={{ marginRight: '15px' }} />
2024-12-21 17:41:53 +05:30
{t('run_content.captured_data.title')}
2024-10-11 01:19:05 +05:30
</Typography>
2024-11-12 10:35:49 +05:30
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, mt: 2 }}>
<Typography>
<a style={{ textDecoration: 'none' }} href={`data:application/json;utf8,${JSON.stringify(row.serializableOutput, null, 2)}`}
download="data.json">
2024-12-21 17:41:53 +05:30
{t('run_content.captured_data.download_json')}
2024-11-12 10:35:49 +05:30
</a>
</Typography>
2024-11-12 10:42:40 +05:30
<Typography
2024-11-12 10:35:49 +05:30
onClick={downloadCSV}
>
2024-12-21 17:41:53 +05:30
<a style={{ textDecoration: 'none', cursor: 'pointer' }}>{t('run_content.captured_data.download_csv')}</a>
2024-11-12 10:42:40 +05:30
</Typography>
2024-11-12 10:35:49 +05:30
</Box>
2024-10-11 01:19:05 +05:30
{tableData.length > 0 ? (
2024-11-12 10:35:49 +05:30
<TableContainer component={Paper} sx={{ maxHeight: 440, marginTop: 2 }}>
<Table stickyHeader aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell key={column}>{column}</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{tableData.map((row, index) => (
<TableRow key={index}>
2024-10-11 01:19:05 +05:30
{columns.map((column) => (
2024-11-20 05:14:03 +05:30
<TableCell key={column}>
{row[column] === undefined || row[column] === "" ? "-" : row[column]}
</TableCell>
2024-10-11 01:19:05 +05:30
))}
</TableRow>
2024-11-12 10:35:49 +05:30
))}
</TableBody>
</Table>
</TableContainer>
2024-10-11 01:19:05 +05:30
) : (
<Box sx={{
width: 'fit-content',
background: 'rgba(0,0,0,0.06)',
maxHeight: '300px',
overflow: 'scroll',
2024-11-24 00:49:39 +05:30
backgroundColor: '#19171c'
2024-10-11 01:19:05 +05:30
}}>
<pre>
{JSON.stringify(row.serializableOutput, null, 2)}
</pre>
</Box>
)}
2024-09-27 23:40:01 +05:30
</div>
}
2024-11-12 10:35:49 +05:30
{row.binaryOutput && Object.keys(row.binaryOutput).length !== 0 &&
2024-09-27 23:40:01 +05:30
<div>
<Typography variant='h6' sx={{ display: 'flex', alignItems: 'center' }}>
<ImageIcon sx={{ marginRight: '15px' }} />
2024-12-21 17:41:53 +05:30
{t('run_content.captured_screenshot.title')}
2024-11-12 10:35:49 +05:30
</Typography>
2024-09-27 23:40:01 +05:30
{Object.keys(row.binaryOutput).map((key) => {
try {
2024-10-16 14:53:59 +05:30
const imageUrl = row.binaryOutput[key];
2024-09-27 23:40:01 +05:30
return (
<Box key={`number-of-binary-output-${key}`} sx={{
width: 'max-content',
}}>
2024-11-12 10:35:49 +05:30
<Typography sx={{ margin: '20px 0px' }}>
2024-12-21 17:41:53 +05:30
<a href={imageUrl} download={key} style={{ textDecoration: 'none' }}>{t('run_content.captured_screenshot.download')}</a>
2024-09-27 23:40:01 +05:30
</Typography>
2024-11-12 10:35:49 +05:30
<img src={imageUrl} alt={key} height='auto' width='700px' />
2024-09-27 23:40:01 +05:30
</Box>
)
} catch (e) {
console.log(e)
return <Typography key={`number-of-binary-output-${key}`}>
2024-12-21 17:41:53 +05:30
{key}: {t('run_content.captured_screenshot.render_failed')}
2024-09-27 23:40:01 +05:30
</Typography>
}
})}
</div>
}
</TabPanel>
2024-06-24 22:38:29 +05:30
</TabContext>
</Box>
);
2024-11-12 10:35:49 +05:30
};