mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
feat: add loading spinner when logs are being loaded
This commit is contained in:
@@ -9,7 +9,7 @@ import {
|
|||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { Download as DownloadIcon } from "lucide-react";
|
import { Download as DownloadIcon, Loader2 } from "lucide-react";
|
||||||
import React, { useEffect, useRef } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { TerminalLine } from "./terminal-line";
|
import { TerminalLine } from "./terminal-line";
|
||||||
import { type LogLine, getLogType, parseLogs } from "./utils";
|
import { type LogLine, getLogType, parseLogs } from "./utils";
|
||||||
@@ -30,7 +30,7 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !!containerId,
|
enabled: !!containerId,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const [rawLogs, setRawLogs] = React.useState("");
|
const [rawLogs, setRawLogs] = React.useState("");
|
||||||
@@ -41,6 +41,7 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
const [since, setSince] = React.useState<TimeFilter>("all");
|
const [since, setSince] = React.useState<TimeFilter>("all");
|
||||||
const [typeFilter, setTypeFilter] = React.useState<TypeFilter>("all");
|
const [typeFilter, setTypeFilter] = React.useState<TypeFilter>("all");
|
||||||
const scrollRef = useRef<HTMLDivElement>(null);
|
const scrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
|
|
||||||
const scrollToBottom = () => {
|
const scrollToBottom = () => {
|
||||||
if (autoScroll && scrollRef.current) {
|
if (autoScroll && scrollRef.current) {
|
||||||
@@ -85,6 +86,7 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!containerId) return;
|
if (!containerId) return;
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
const params = new globalThis.URLSearchParams({
|
const params = new globalThis.URLSearchParams({
|
||||||
@@ -106,19 +108,22 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
console.log("WebSocket connected");
|
console.log("WebSocket connected");
|
||||||
|
setIsLoading(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onmessage = (e) => {
|
ws.onmessage = (e) => {
|
||||||
// console.log("Received message:", e.data);
|
|
||||||
setRawLogs((prev) => prev + e.data);
|
setRawLogs((prev) => prev + e.data);
|
||||||
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onerror = (error) => {
|
ws.onerror = (error) => {
|
||||||
console.error("WebSocket error:", error);
|
console.error("WebSocket error:", error);
|
||||||
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onclose = (e) => {
|
ws.onclose = (e) => {
|
||||||
console.log("WebSocket closed:", e.reason);
|
console.log("WebSocket closed:", e.reason);
|
||||||
|
setIsLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -132,7 +137,7 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
const logContent = filteredLogs
|
const logContent = filteredLogs
|
||||||
.map(
|
.map(
|
||||||
({ timestamp, message }: { timestamp: Date | null; message: string }) =>
|
({ timestamp, message }: { timestamp: Date | null; message: string }) =>
|
||||||
`${timestamp?.toISOString() || "No timestamp"} ${message}`,
|
`${timestamp?.toISOString() || "No timestamp"} ${message}`
|
||||||
)
|
)
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
@@ -142,7 +147,9 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
const appName = data.Name.replace("/", "") || "app";
|
const appName = data.Name.replace("/", "") || "app";
|
||||||
const isoDate = new Date().toISOString();
|
const isoDate = new Date().toISOString();
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = `${appName}-${isoDate.slice(0, 10).replace(/-/g, "")}_${isoDate.slice(11, 19).replace(/:/g, "")}.log.txt`;
|
a.download = `${appName}-${isoDate.slice(0, 10).replace(/-/g, "")}_${isoDate
|
||||||
|
.slice(11, 19)
|
||||||
|
.replace(/:/g, "")}.log.txt`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
@@ -262,6 +269,10 @@ export const DockerLogsId: React.FC<Props> = ({ containerId, serverId }) => {
|
|||||||
searchTerm={search}
|
searchTerm={search}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
|
) : isLoading ? (
|
||||||
|
<div className="flex justify-center items-center h-full text-muted-foreground">
|
||||||
|
<Loader2 className="h-6 w-6 animate-spin" />
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-center items-center h-full text-muted-foreground">
|
<div className="flex justify-center items-center h-full text-muted-foreground">
|
||||||
No logs found
|
No logs found
|
||||||
|
|||||||
Reference in New Issue
Block a user