ui: add jump and sync for backend logs
This commit is contained in:
parent
36edfd8413
commit
fc63e4d83d
2 changed files with 51 additions and 42 deletions
|
|
@ -2,6 +2,7 @@ import { useQuery } from '@tanstack/react-query';
|
|||
import { Segmented } from 'antd';
|
||||
import React from 'react';
|
||||
import { VList, VListHandle } from 'virtua';
|
||||
import { PlayerContext } from "App/components/Session/playerContext";
|
||||
import { processLog, UnifiedLog } from './utils';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -32,6 +33,7 @@ async function fetchLogs(
|
|||
const logsResp = await fetch(json.url)
|
||||
if (logsResp.ok) {
|
||||
const logJson = await logsResp.json()
|
||||
if (logJson.length === 0) return []
|
||||
return processLog(logJson)
|
||||
} else {
|
||||
throw new Error('Failed to fetch logs')
|
||||
|
|
@ -59,16 +61,7 @@ function BackendLogsPanel() {
|
|||
enabled: tab !== null,
|
||||
retry: 3,
|
||||
});
|
||||
|
||||
console.log(isError, isPending, isSuccess)
|
||||
const [filter, setFilter] = React.useState('');
|
||||
const _list = React.useRef<VListHandle>(null);
|
||||
const activeIndex = 1;
|
||||
React.useEffect(() => {
|
||||
if (_list.current) {
|
||||
_list.current.scrollToIndex(activeIndex);
|
||||
}
|
||||
}, [activeIndex]);
|
||||
|
||||
const onFilterChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilter(e.target.value);
|
||||
|
|
@ -122,40 +115,44 @@ function BackendLogsPanel() {
|
|||
/>
|
||||
) : null}
|
||||
{isSuccess ? (
|
||||
<>
|
||||
<TableHeader size={data.length} />
|
||||
<VList ref={_list} count={testLogs.length}>
|
||||
{data.map((log, index) => (
|
||||
<LogRow key={index} log={log} />
|
||||
))}
|
||||
</VList>
|
||||
</>
|
||||
<LogsTable data={data} />
|
||||
) : null}
|
||||
</BottomBlock.Content>
|
||||
</BottomBlock>
|
||||
);
|
||||
}
|
||||
|
||||
const testLogs = [
|
||||
{
|
||||
key: 1,
|
||||
timestamp: '2021-09-01 12:00:00',
|
||||
status: 'INFO',
|
||||
content: 'This is a test log',
|
||||
},
|
||||
{
|
||||
key: 2,
|
||||
timestamp: '2021-09-01 12:00:00',
|
||||
status: 'WARN',
|
||||
content: 'This is a test log',
|
||||
},
|
||||
{
|
||||
key: 3,
|
||||
timestamp: '2021-09-01 12:00:00',
|
||||
status: 'ERROR',
|
||||
content:
|
||||
'This is a test log that is very long and should be truncated to fit in the table cell and it will be displayed later in a separate thing when clicked on a row because its so long you never gonna give htem up or alskjhaskfjhqwfhwekfqwfjkqlwhfkjqhflqkwjhefqwklfehqwlkfjhqwlkjfhqwe \n kjhdafskjfhlqkwjhfwelefkhwqlkqehfkqlwehfkqwhefkqhwefkjqwhf',
|
||||
},
|
||||
];
|
||||
const LogsTable = observer(({ data }: { data: UnifiedLog[] }) => {
|
||||
const { store, player } = React.useContext(PlayerContext);
|
||||
const time = store.get().time;
|
||||
const sessionStart = store.get().sessionStart;
|
||||
const _list = React.useRef<VListHandle>(null);
|
||||
const activeIndex = React.useMemo(() => {
|
||||
const currTs = time + sessionStart;
|
||||
const index = data.findIndex(
|
||||
(log) => log.timestamp !== 'N/A' ? new Date(log.timestamp).getTime() >= currTs : false
|
||||
);
|
||||
return index === -1 ? data.length - 1 : index;
|
||||
}, [time, data.length]);
|
||||
React.useEffect(() => {
|
||||
if (_list.current) {
|
||||
_list.current.scrollToIndex(activeIndex);
|
||||
}
|
||||
}, [activeIndex]);
|
||||
|
||||
const onJump = (ts: number) => {
|
||||
player.jump(ts - sessionStart);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<TableHeader size={data.length} />
|
||||
<VList ref={_list} count={data.length}>
|
||||
{data.map((log, index) => (
|
||||
<LogRow key={index} isActive={index === activeIndex} log={log} onJump={onJump} />
|
||||
))}
|
||||
</VList>
|
||||
</>
|
||||
)
|
||||
});
|
||||
|
||||
export default observer(BackendLogsPanel);
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Button } from 'antd';
|
|||
import cn from 'classnames';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { getDateFromString } from 'App/date';
|
||||
import JumpButton from 'App/components/shared/DevTools/JumpButton';
|
||||
|
||||
export function TableHeader({ size }: { size: number }) {
|
||||
return (
|
||||
|
|
@ -28,8 +29,12 @@ export function TableHeader({ size }: { size: number }) {
|
|||
|
||||
export function LogRow({
|
||||
log,
|
||||
onJump,
|
||||
isActive,
|
||||
}: {
|
||||
log: { timestamp: string; status: string; content: string };
|
||||
onJump: (ts: number) => void;
|
||||
isActive?: boolean;
|
||||
}) {
|
||||
const [isExpanded, setIsExpanded] = React.useState(false);
|
||||
const bg = (status: string) => {
|
||||
|
|
@ -54,13 +59,16 @@ export function LogRow({
|
|||
return 'border-l border-l-4 border-gray-lighter';
|
||||
};
|
||||
return (
|
||||
<div className={'code-font'}>
|
||||
<div
|
||||
className={'code-font relative group'}
|
||||
>
|
||||
<JumpButton onClick={() => onJump(new Date(log.timestamp).getTime())} />
|
||||
<div
|
||||
className={cn(
|
||||
'text-sm grid items-center py-2 px-4',
|
||||
'cursor-pointer border-b border-b-gray-light last:border-b-0',
|
||||
border(log.status),
|
||||
bg(log.status)
|
||||
isActive ? 'bg-gray-lightest' : bg(log.status)
|
||||
)}
|
||||
style={{
|
||||
gridTemplateColumns: 'repeat(14, minmax(0, 1fr))',
|
||||
|
|
@ -90,10 +98,14 @@ export function LogRow({
|
|||
</div>
|
||||
</div>
|
||||
{isExpanded ? (
|
||||
<div className={'rounded bg-gray-lightest px-4 py-2 relative mx-4 my-2'}>
|
||||
<div
|
||||
className={'rounded bg-gray-lightest px-4 py-2 relative mx-4 my-2'}
|
||||
>
|
||||
{log.content.split('\n').map((line, index) => (
|
||||
<div key={index} className={'flex items-start gap-2'}>
|
||||
<div className={'border-r border-r-gray-light pr-2 select-none'}>{index}</div>
|
||||
<div className={'border-r border-r-gray-light pr-2 select-none'}>
|
||||
{index}
|
||||
</div>
|
||||
<div className={'whitespace-pre-wrap'}>{line}</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue