Logs auto scroll
This commit is contained in:
+32
-2
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { DashboardLayout } from "@/components/dashboard/DashboardLayout";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -14,6 +14,10 @@ import { AnsiText } from "@/components/ansi/Ansi";
|
||||
|
||||
export default function LogsPage() {
|
||||
const [isPaused, setIsPaused] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const bottomRef = useRef<HTMLDivElement>(null);
|
||||
const shouldAutoScroll = useRef(true);
|
||||
|
||||
const [filter, setFilter] = useState<"all" | "info" | "warn" | "error">(
|
||||
"all",
|
||||
);
|
||||
@@ -28,6 +32,25 @@ export default function LogsPage() {
|
||||
filter === "all" ? true : log.level === filter,
|
||||
);
|
||||
|
||||
const handleScroll = () => {
|
||||
const el = containerRef.current;
|
||||
if (!el) return;
|
||||
|
||||
const threshold = 20; // px from bottom
|
||||
const isAtBottom =
|
||||
el.scrollHeight - el.scrollTop - el.clientHeight < threshold;
|
||||
|
||||
shouldAutoScroll.current = isAtBottom;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldAutoScroll.current || isPaused) return;
|
||||
|
||||
bottomRef.current?.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
});
|
||||
}, [filteredLogs, isPaused]);
|
||||
|
||||
const handleExport = () => {
|
||||
// Convert data to JSON string
|
||||
const json = JSON.stringify(filteredLogs, null, 2);
|
||||
@@ -156,7 +179,11 @@ export default function LogsPage() {
|
||||
</div>
|
||||
</CardHeader>
|
||||
|
||||
<CardContent className="p-0 overflow-auto h-[calc(100%-48px)]">
|
||||
<CardContent
|
||||
className="p-0 overflow-auto h-[calc(100%-48px)]"
|
||||
ref={containerRef}
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
<div className="font-mono text-xs px-3 md:px-6 space-y-2 md:space-y-0">
|
||||
{filteredLogs.map((log, index) => (
|
||||
<div
|
||||
@@ -188,6 +215,9 @@ export default function LogsPage() {
|
||||
{log.message}
|
||||
</span> */}
|
||||
<AnsiText text={log.message} />
|
||||
|
||||
{/* Scroll anchor */}
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user