mirror of
https://github.com/andwati/dokploy.git
synced 2026-10-25 14:32:17 +00:00
Merge pull request #5137 from bestmaa/fix/5111-preserve-log-container-selection
fix: preserve selected log container on refetch
(cherry picked from commit f4dfb6a903)
[skip ci]
This commit is contained in:
committed by
Dokploy Bot
parent
b4edb56132
commit
d3d8d9ec83
@@ -0,0 +1,41 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
import { resolveContainerSelection } from "@/components/dashboard/docker/logs/utils";
|
||||||
|
|
||||||
|
const containers = [
|
||||||
|
{ containerId: "first-container" },
|
||||||
|
{ containerId: "selected-container" },
|
||||||
|
];
|
||||||
|
|
||||||
|
describe("resolveContainerSelection", () => {
|
||||||
|
it("selects the first container when no container is selected", () => {
|
||||||
|
expect(resolveContainerSelection(undefined, containers)).toBe(
|
||||||
|
"first-container",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves a manual selection when refreshed data contains it", () => {
|
||||||
|
const refreshedContainers = containers.map((container) => ({
|
||||||
|
...container,
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(
|
||||||
|
resolveContainerSelection("selected-container", refreshedContainers),
|
||||||
|
).toBe("selected-container");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("falls back to the first container when the selection disappears", () => {
|
||||||
|
expect(resolveContainerSelection("removed-container", containers)).toBe(
|
||||||
|
"first-container",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps the current selection while container data is loading", () => {
|
||||||
|
expect(resolveContainerSelection("selected-container", undefined)).toBe(
|
||||||
|
"selected-container",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("clears the selection when no containers are available", () => {
|
||||||
|
expect(resolveContainerSelection("selected-container", [])).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { resolveContainerSelection } from "@/components/dashboard/docker/logs/utils";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -79,17 +80,13 @@ export const ShowDockerLogs = ({ appName, serverId, serviceId }: Props) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const availableContainers = option === "native" ? containers : services;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (option === "native") {
|
setContainerId((currentContainerId) =>
|
||||||
if (containers && containers?.length > 0) {
|
resolveContainerSelection(currentContainerId, availableContainers),
|
||||||
setContainerId(containers[0]?.containerId);
|
);
|
||||||
}
|
}, [availableContainers]);
|
||||||
} else {
|
|
||||||
if (services && services?.length > 0) {
|
|
||||||
setContainerId(services[0]?.containerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [option, services, containers]);
|
|
||||||
|
|
||||||
const isLoading = option === "native" ? containersLoading : servicesLoading;
|
const isLoading = option === "native" ? containersLoading : servicesLoading;
|
||||||
const containersLength =
|
const containersLength =
|
||||||
@@ -114,6 +111,7 @@ export const ShowDockerLogs = ({ appName, serverId, serviceId }: Props) => {
|
|||||||
<Switch
|
<Switch
|
||||||
checked={option === "native"}
|
checked={option === "native"}
|
||||||
onCheckedChange={(checked) => {
|
onCheckedChange={(checked) => {
|
||||||
|
setContainerId(undefined);
|
||||||
setOption(checked ? "native" : "swarm");
|
setOption(checked ? "native" : "swarm");
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Loader2 } from "lucide-react";
|
|||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { badgeStateColor } from "@/components/dashboard/application/logs/show";
|
import { badgeStateColor } from "@/components/dashboard/application/logs/show";
|
||||||
|
import { resolveContainerSelection } from "@/components/dashboard/docker/logs/utils";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -70,22 +71,13 @@ export const ShowDockerLogsStack = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const containers = data?.filter((container) => container.containerId);
|
const containers = data?.filter((container) => container.containerId);
|
||||||
|
const availableContainers = option === "native" ? containers : services;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const currentContainers = option === "native" ? containers : services;
|
setContainerId((currentContainerId) =>
|
||||||
|
resolveContainerSelection(currentContainerId, availableContainers),
|
||||||
if (currentContainers) {
|
);
|
||||||
const nextContainerId = currentContainers.some(
|
}, [availableContainers]);
|
||||||
(container) => container.containerId === containerId,
|
|
||||||
)
|
|
||||||
? containerId
|
|
||||||
: currentContainers[0]?.containerId;
|
|
||||||
|
|
||||||
if (nextContainerId !== containerId) {
|
|
||||||
setContainerId(nextContainerId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [option, services, containers, containerId]);
|
|
||||||
|
|
||||||
const isLoading = option === "native" ? containersLoading : servicesLoading;
|
const isLoading = option === "native" ? containersLoading : servicesLoading;
|
||||||
const containersLength =
|
const containersLength =
|
||||||
|
|||||||
@@ -7,6 +7,28 @@ export interface LogLine {
|
|||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ContainerOption {
|
||||||
|
containerId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resolveContainerSelection = (
|
||||||
|
currentContainerId: string | undefined,
|
||||||
|
containers: readonly ContainerOption[] | undefined,
|
||||||
|
) => {
|
||||||
|
if (!containers) {
|
||||||
|
return currentContainerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
currentContainerId &&
|
||||||
|
containers.some(({ containerId }) => containerId === currentContainerId)
|
||||||
|
) {
|
||||||
|
return currentContainerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return containers[0]?.containerId;
|
||||||
|
};
|
||||||
|
|
||||||
interface LogStyle {
|
interface LogStyle {
|
||||||
type: LogType;
|
type: LogType;
|
||||||
variant: LogVariant;
|
variant: LogVariant;
|
||||||
|
|||||||
Reference in New Issue
Block a user