Skip to content
This repository was archived by the owner on May 13, 2025. It is now read-only.
96 changes: 84 additions & 12 deletions src/pages/Stream/Views/Explore/StaticLogRow.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { parseLogData } from '@/utils';
import { Box } from '@mantine/core';
import { Group, Stack, ActionIcon, Tooltip, Box } from '@mantine/core';
import { IconArrowNarrowRight } from '@tabler/icons-react';
import { FC, Fragment, useCallback } from 'react';
import { FC, Fragment, useCallback, MouseEvent, useState, useEffect } from 'react';
import { Log } from '@/@types/parseable/api/query';
import tableStyles from '../../styles/Logs.module.css';
import { useLogsStore, logsStoreReducers } from '../../providers/LogsProvider';
import { IconCopy, IconCheck } from '@tabler/icons-react';

const columnsToSkip = ['p_metadata', 'p_tags'];

Expand All @@ -15,7 +16,46 @@ type LogRowProps = {
isPinned?: boolean;
};

const CopyButton = (props: { fieldValue: any }) => {
const [copied, setCopied] = useState(false);

useEffect(() => {
if (copied) {
const timer = setTimeout(() => {
setCopied(false);
}, 2000);
return () => clearTimeout(timer);
}
}, [copied]);

const copy = useCallback(async () => {
await navigator.clipboard.writeText(props.fieldValue);
}, [props.fieldValue]);

const handleCopyBtnClick = useCallback(
async (e: MouseEvent) => {
e.stopPropagation();
await copy();
setCopied(true);
},
[copy],
);

return (
<Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
<ActionIcon variant="subtle" onClick={handleCopyBtnClick}>
{copied ? (
<IconCheck size={12} style={{ backgroundColor: 'transparent', color: '#211F1F' }} stroke={1.5} />
) : (
<IconCopy size={12} style={{ backgroundColor: 'transparent', color: '#211F1F' }} stroke={1.5} />
)}
</ActionIcon>
</Tooltip>
);
};

const LogRow: FC<LogRowProps> = (props) => {
const [hoveredCell, setHoveredCell] = useState<string | null>(null);
const { isPinned, rowArrows } = props;
const classes = tableStyles;
const { trStyle, trEvenStyle } = classes;
Expand All @@ -27,21 +67,53 @@ const LogRow: FC<LogRowProps> = (props) => {
...headers.filter((header) => (isPinned ? !pinnedColumns.includes(header) : pinnedColumns.includes(header))),
];
const columnsToShow = headers.filter((header) => !columnsToIgnore.includes(header));

const handleMouseLeave = useCallback(() => {
setHoveredCell(null);
}, []);

const handleMouseEnter = useCallback((row: number, column: number) => {
setHoveredCell(`${row}-${column}`);
}, []);

const onClick = useCallback((log: Log) => {
const selectedText = window.getSelection()?.toString();
if (selectedText !== undefined && selectedText?.length > 0) return;

setLogsStore((store) => setSelectedLog(store, log));
}, []);

return (
<Fragment>
{pageData.map((log, logIndex) => {
return (
<tr key={logIndex} className={logIndex % 2 ? trStyle : trEvenStyle} onClick={() => onClick(log)}>
{columnsToShow.map((header, logSchemaIndex) => {
return <td key={`${header}-${logSchemaIndex}`}>{parseLogData(log[header], header)}</td>;
})}
{rowArrows && <ViewLogArrow />}
</tr>
);
})}
{pageData.map((log, logIndex) => (
<tr key={logIndex} className={logIndex % 2 ? trStyle : trEvenStyle} onClick={() => onClick(log)}>
{columnsToShow.map((header, logSchemaIndex) => {
const parsedData = parseLogData(log[header], header);

return (
<td
key={`${header}-${logSchemaIndex}`}
onMouseEnter={() => handleMouseEnter(logIndex, logSchemaIndex)}
onMouseLeave={handleMouseLeave}>
<Group style={{ position: 'relative' }} wrap="nowrap">
{parsedData}
{hoveredCell === `${logIndex}-${logSchemaIndex}` && (
<Stack
style={{
position: 'absolute',
right: '0',
background: 'white',
}}>
<CopyButton fieldValue={parsedData} />
</Stack>
)}
</Group>
</td>
);
})}
{rowArrows && <ViewLogArrow />}
</tr>
))}
</Fragment>
);
};
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Stream/components/ViewLog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const Header: FC<HeaderProps> = (props) => {
const { onClose } = props;
const classes = viewLogStyles;

const { headerContainer, headerTimeStampTitle, headerTimeStamp } = classes;
const { headerContainer, headerTimeStampTitle, headerTimeStamp, closeBtn } = classes;

const timeStamp = useMemo(() => dayjs(`${props.timeStamp}+00:00`).utc().format('DD/MM/YYYY (hh:mm:ss A) z'), []);

Expand All @@ -84,7 +84,7 @@ const Header: FC<HeaderProps> = (props) => {
<Box />
)}

<CloseButton iconSize={px('1.5rem')} onClick={onClose} />
<CloseButton className={closeBtn} iconSize={px('1.5rem')} onClick={onClose} />
</Box>
);
};
Expand Down
Loading