This commit is contained in:
2026-08-12 19:30:17 +03:00
parent 40c324d7fe
commit b0b7196518
152 changed files with 24657 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
import { useEffect, useRef, useCallback } from 'react';
import { LogEntry } from '../../api/types';
import { LogEntry as LogEntryComponent } from './LogEntry';
import { cn } from '../../utils/helpers';
interface LogStreamProps {
logs: LogEntry[];
isLoading?: boolean;
isLive?: boolean;
autoScroll?: boolean;
className?: string;
maxHeight?: string;
}
export function LogStream({
logs,
isLoading = false,
isLive = false,
autoScroll = true,
className,
maxHeight = '500px',
}: LogStreamProps) {
const containerRef = useRef<HTMLDivElement>(null);
const prevLogsLength = useRef(logs.length);
const scrollToBottom = useCallback(() => {
if (containerRef.current) {
containerRef.current.scrollTop = containerRef.current.scrollHeight;
}
}, []);
useEffect(() => {
if (autoScroll && logs.length > prevLogsLength.current) {
scrollToBottom();
}
prevLogsLength.current = logs.length;
}, [logs.length, autoScroll, scrollToBottom]);
return (
<div
ref={containerRef}
className={cn(
'overflow-y-auto rounded-lg border border-border bg-card font-mono text-sm',
className
)}
style={{ maxHeight }}
>
{isLoading && logs.length === 0 ? (
<div className="flex items-center justify-center p-8 text-muted-foreground">
Загрузка логов...
</div>
) : logs.length === 0 ? (
<div className="flex items-center justify-center p-8 text-muted-foreground">
Нет логов для отображения
</div>
) : (
<div className="divide-y divide-border">
{logs.map((log) => (
<LogEntryComponent key={log.id} log={log} />
))}
</div>
)}
{isLive && (
<div className="sticky bottom-0 left-0 right-0 flex items-center justify-center gap-2 border-t border-border bg-card/95 p-2 text-xs text-green-400 backdrop-blur">
<span className="relative flex h-2 w-2">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-green-400" />
</span>
Прямой эфир
</div>
)}
</div>
);
}
export default LogStream;