diff --git a/ui/src/components/docker/container-stats.tsx b/ui/src/components/docker/container-stats.tsx new file mode 100644 index 000000000..21118923e --- /dev/null +++ b/ui/src/components/docker/container-stats.tsx @@ -0,0 +1,87 @@ + +import { DataTable, SortableHeader } from "@/ui/data-table"; + +import { Group, Text } from "@mantine/core"; +import DockerResourceLink from "@/components/docker/link"; +import { filterBySplit } from "@/lib/utils"; +import { Types } from "komodo_client"; + +export interface ContainerStatsProps { + containers: Types.ContainerListItem[]; + search: string; +} + +export default function ContainerStats({containers, search}: ContainerStatsProps) { + const filtered = filterBySplit( + containers, + search, + (container) => container.name, + ); + return ( + ( + + ), + cell: ({ row }) => ( + + ), + }, + { + accessorKey: "stats.cpu_perc", + size: 100, + header: ({ column }) => ( + + ), + }, + { + accessorKey: "stats.mem_perc", + size: 200, + header: ({ column }) => ( + + ), + cell: ({ row }) => ( + + {row.original.stats?.mem_perc} + + ({row.original.stats?.mem_usage}) + + + ), + }, + { + accessorKey: "stats.net_io", + size: 150, + header: ({ column }) => ( + + ), + }, + { + accessorKey: "stats.block_io", + size: 150, + header: ({ column }) => ( + + ), + }, + { + accessorKey: "stats.pids", + size: 100, + header: ({ column }) => ( + + ), + }, + ]} + /> + ); +} \ No newline at end of file diff --git a/ui/src/resources/server/stats/containers.tsx b/ui/src/resources/server/stats/containers.tsx index 912ca8052..8840979a1 100644 --- a/ui/src/resources/server/stats/containers.tsx +++ b/ui/src/resources/server/stats/containers.tsx @@ -1,15 +1,13 @@ import { useRead } from "@/lib/hooks"; -import { DataTable, SortableHeader } from "@/ui/data-table"; -import Section from "@/ui/section"; -import ShowHideButton from "@/ui/show-hide-button"; -import { Group, Text } from "@mantine/core"; import { useLocalStorage } from "@mantine/hooks"; import { useState } from "react"; -import { filterBySplit } from "@/lib/utils"; -import DockerResourceLink from "@/components/docker/link"; import { useIsServerAvailable } from "../hooks"; +import ContainerStats from "@/components/docker/container-stats"; import SearchInput from "@/ui/search-input"; import { ICONS } from "@/theme/icons"; +import Section from "@/ui/section"; +import ShowHideButton from "@/ui/show-hide-button"; +import { Group } from "@mantine/core"; export default function ServerContainerStats({ id }: { id: string }) { const [search, setSearch] = useState(""); @@ -27,95 +25,24 @@ export default function ServerContainerStats({ id }: { id: string }) { enabled: isServerAvailable && show, }, ).data?.filter((c) => c.stats); - const filtered = filterBySplit( - containers, - search, - (container) => container.name, - ); return ( -
} - titleRight={ - - - - - } - onHeaderClick={() => setShow((s) => !s)} - > - {show && ( - ( - - ), - cell: ({ row }) => ( - - ), - }, - { - accessorKey: "stats.cpu_perc", - size: 100, - header: ({ column }) => ( - - ), - }, - { - accessorKey: "stats.mem_perc", - size: 200, - header: ({ column }) => ( - - ), - cell: ({ row }) => ( - - {row.original.stats?.mem_perc} - - ({row.original.stats?.mem_usage}) - - - ), - }, - { - accessorKey: "stats.net_io", - size: 150, - header: ({ column }) => ( - - ), - }, - { - accessorKey: "stats.block_io", - size: 150, - header: ({ column }) => ( - - ), - }, - { - accessorKey: "stats.pids", - size: 100, - header: ({ column }) => ( - - ), - }, - ]} - /> - )} -
- ); +
} + titleRight={ + + + + + } + onHeaderClick={() => setShow((s) => !s)} + > + +
+ ) } diff --git a/ui/src/resources/stack/stats/container.tsx b/ui/src/resources/stack/stats/container.tsx new file mode 100644 index 000000000..36a5f662f --- /dev/null +++ b/ui/src/resources/stack/stats/container.tsx @@ -0,0 +1,37 @@ +import { useRead } from "@/lib/hooks"; +import { Types } from "komodo_client"; +import { ReactNode, useState } from "react"; +import { useStack } from ".."; +import ContainerStats from "@/components/docker/container-stats"; +import Section from "@/ui/section"; +import { Group } from "@mantine/core"; +import SearchInput from "@/ui/search-input"; + +export default function StackContainerStats({ id, titleOther }: { id: string, titleOther: ReactNode }) { + const [search, setSearch] = useState(""); + const isStackAvailable = useStack(id)?.info.state !== Types.StackState.Down; + const containers = useRead( + "ListStackServices", + { + stack: id, + }, + { + enabled: isStackAvailable, + }, + ).data?.map((c) => c.container).filter(c => c !== undefined); + return ( +
+
+ + + }> + +
+
+ ) +} diff --git a/ui/src/resources/stack/tabs.tsx b/ui/src/resources/stack/tabs.tsx index 21fe36201..6a33c7e43 100644 --- a/ui/src/resources/stack/tabs.tsx +++ b/ui/src/resources/stack/tabs.tsx @@ -16,8 +16,9 @@ import StackInfo from "./info"; import StackServices from "./services"; import StackLog from "./log"; import TerminalSection from "@/components/terminal/section"; +import StackContainerStats from "./stats/container"; -type StackTabsView = "Config" | "Info" | "Services" | "Log" | "Terminals"; +type StackTabsView = "Config" | "Info" | "Services" | "Log" | "Terminals" | "Stats"; export default function StackTabs({ id }: { id: string }) { const [_view, setView] = useLocalStorage({ @@ -87,6 +88,10 @@ export default function StackTabs({ id }: { id: string }) { hidden: !specificTerminal, icon: ICONS.Terminal, }, + { + value: "Stats", + icon: ICONS.Stats, + }, ], [ hideInfo, @@ -139,6 +144,9 @@ export default function StackTabs({ id }: { id: string }) { /> ); break; + case "Stats": + View = ; + break; } return (