Merge remote-tracking branch 'origin/feat/docker-logs' into insiders/ui-ux
# Conflicts: # apps/nextjs/src/app/[locale]/manage/tools/docker/docker-table.tsx # apps/nextjs/src/app/[locale]/manage/tools/logs/terminal.tsx # apps/nextjs/src/components/layout/navigation-link.tsx # pnpm-lock.yaml
This commit is contained in:
10 files changed
+437
-476
No files matched your search
@@ -2,7 +2,7 @@
|
||||
|
||||
import type { PropsWithChildren } from "react";
|
||||
import type { MantineColorScheme, MantineColorSchemeManager } from "@mantine/core";
|
||||
import { DirectionProvider, MantineProvider } from "@mantine/core";
|
||||
import { DirectionProvider, MantineProvider, v8CssVariablesResolver } from "@mantine/core";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
@@ -18,7 +18,12 @@ export const CustomMantineProvider = ({
|
||||
const manager = useColorSchemeManager();
|
||||
return (
|
||||
<DirectionProvider>
|
||||
<MantineProvider defaultColorScheme={defaultColorScheme} colorSchemeManager={manager} theme={theme}>
|
||||
<MantineProvider
|
||||
defaultColorScheme={defaultColorScheme}
|
||||
colorSchemeManager={manager}
|
||||
theme={theme}
|
||||
cssVariablesResolver={v8CssVariablesResolver}
|
||||
>
|
||||
{children}
|
||||
</MantineProvider>
|
||||
</DirectionProvider>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import type { PropsWithChildren } from "react";
|
||||
import type { MantineColorsTuple } from "@mantine/core";
|
||||
import { colorsTuple, createTheme, darken, lighten, MantineProvider, rem } from "@mantine/core";
|
||||
import { colorsTuple, createTheme, darken, lighten, MantineProvider, rem, v8CssVariablesResolver } from "@mantine/core";
|
||||
|
||||
import { useRequiredBoard } from "@homarr/boards/context";
|
||||
import type { ColorScheme } from "@homarr/definitions";
|
||||
@@ -33,7 +33,12 @@ export const BoardMantineProvider = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<MantineProvider defaultColorScheme={defaultColorScheme} theme={theme} colorSchemeManager={colorSchemeManager}>
|
||||
<MantineProvider
|
||||
defaultColorScheme={defaultColorScheme}
|
||||
theme={theme}
|
||||
colorSchemeManager={colorSchemeManager}
|
||||
cssVariablesResolver={v8CssVariablesResolver}
|
||||
>
|
||||
{children}
|
||||
</MantineProvider>
|
||||
);
|
||||
|
||||
@@ -159,6 +159,23 @@ export function DockerTable({ containers, timestamp }: RouterOutputs["docker"]["
|
||||
refetchOnReconnect: false,
|
||||
});
|
||||
const relativeTime = useTimeAgo(data.timestamp);
|
||||
const utils = clientApi.useUtils();
|
||||
const { mutate, isPending } = clientApi.docker.invalidate.useMutation({
|
||||
async onSuccess() {
|
||||
await utils.docker.getContainers.invalidate();
|
||||
showSuccessNotification({
|
||||
title: tDocker("action.refresh.notification.success.title"),
|
||||
message: tDocker("action.refresh.notification.success.message"),
|
||||
});
|
||||
},
|
||||
onError() {
|
||||
showErrorNotification({
|
||||
title: tDocker("action.refresh.notification.error.title"),
|
||||
message: tDocker("action.refresh.notification.error.message"),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const table = useTranslatedMantineReactTable({
|
||||
data: data.containers,
|
||||
enableDensityToggle: false,
|
||||
@@ -194,35 +211,11 @@ export function DockerTable({ containers, timestamp }: RouterOutputs["docker"]["
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
),
|
||||
renderTopToolbarCustomActions: () => {
|
||||
const utils = clientApi.useUtils();
|
||||
const { mutate, isPending } = clientApi.docker.invalidate.useMutation({
|
||||
async onSuccess() {
|
||||
await utils.docker.getContainers.invalidate();
|
||||
showSuccessNotification({
|
||||
title: tDocker("action.refresh.notification.success.title"),
|
||||
message: tDocker("action.refresh.notification.success.message"),
|
||||
});
|
||||
},
|
||||
onError() {
|
||||
showErrorNotification({
|
||||
title: tDocker("action.refresh.notification.error.title"),
|
||||
message: tDocker("action.refresh.notification.error.message"),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="default"
|
||||
rightSection={<IconRefresh size="1rem" />}
|
||||
onClick={() => mutate()}
|
||||
loading={isPending}
|
||||
>
|
||||
{tDocker("action.refresh.label")}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
renderTopToolbarCustomActions: () => (
|
||||
<Button variant="default" rightSection={<IconRefresh size="1rem" />} onClick={() => mutate()} loading={isPending}>
|
||||
{tDocker("action.refresh.label")}
|
||||
</Button>
|
||||
),
|
||||
renderToolbarAlertBannerContent: ({ groupedAlert, table }) => {
|
||||
const dockerContainers = table.getSelectedRowModel().rows.map((row) => row.original);
|
||||
return (
|
||||
@@ -284,7 +277,6 @@ const ContainerActionBar = ({ selectedContainers }: ContainerActionBarProps) =>
|
||||
onClick={handleShowLogs}
|
||||
disabled={selectedContainers.length !== 1}
|
||||
variant="light"
|
||||
radius="md"
|
||||
>
|
||||
{t("logs.label")}
|
||||
</Button>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { Box, Group, Title } from "@mantine/core";
|
||||
import { Box, Group } from "@mantine/core";
|
||||
|
||||
import { api } from "@homarr/api/server";
|
||||
import { auth } from "@homarr/auth/next";
|
||||
import { env } from "@homarr/docker/env";
|
||||
import { getScopedI18n } from "@homarr/translation/server";
|
||||
|
||||
import "@xterm/xterm/css/xterm.css";
|
||||
|
||||
@@ -32,16 +31,14 @@ export default async function DockerContainerLogsPage({ params, searchParams }:
|
||||
notFound();
|
||||
}
|
||||
|
||||
const tDocker = await getScopedI18n("docker");
|
||||
|
||||
return (
|
||||
<>
|
||||
<Group justify="space-between" align="center" wrap="nowrap">
|
||||
<DynamicBreadcrumb />
|
||||
<DynamicBreadcrumb
|
||||
dynamicMappings={new Map([[containerId, name ?? containerId]])}
|
||||
nonInteractable={[containerId]}
|
||||
/>
|
||||
</Group>
|
||||
<Title order={2} mb="md">
|
||||
{tDocker("action.logs.page.title", { name: name ?? containerId })}
|
||||
</Title>
|
||||
<Box style={{ borderRadius: 6 }} h={fullHeightWithoutHeaderAndFooter} p="md" bg="black">
|
||||
<ClientSideDockerLogsTerminal containerId={containerId} />
|
||||
</Box>
|
||||
|
||||
@@ -51,6 +51,7 @@ export const DockerLogsTerminal = ({ containerId }: DockerLogsTerminalProps) =>
|
||||
cursorBlink: false,
|
||||
disableStdin: true,
|
||||
convertEol: true,
|
||||
fontSize: 14,
|
||||
});
|
||||
terminalRef.current.open(ref.current);
|
||||
terminalRef.current.loadAddon(canvasAddon);
|
||||
|
||||
@@ -26,7 +26,7 @@ const NavLinkHref = (props: NavigationLinkHref) => {
|
||||
label={props.label}
|
||||
leftSection={props.icon}
|
||||
href={props.href}
|
||||
active={pathname === props.href}
|
||||
active={pathname === props.href || pathname.startsWith(`${props.href}/`)}
|
||||
/>
|
||||
);
|
||||
return <TourTarget id={tourId}>{link}</TourTarget>;
|
||||
@@ -34,7 +34,7 @@ const NavLinkHref = (props: NavigationLinkHref) => {
|
||||
|
||||
const NavLinkWithItems = (props: NavigationLinkWithItems) => {
|
||||
const pathname = usePathname();
|
||||
const isActive = props.items.some((item) => item.href === pathname);
|
||||
const isActive = props.items.some((item) => pathname === item.href || pathname.startsWith(`${item.href}/`));
|
||||
const nav = (
|
||||
<NavLink label={props.label} leftSection={props.icon} defaultOpened={isActive}>
|
||||
{props.items.map((item) => (
|
||||
|
||||
@@ -4510,7 +4510,10 @@
|
||||
"label": "Tasks"
|
||||
},
|
||||
"docker": {
|
||||
"label": "Docker"
|
||||
"label": "Docker",
|
||||
"logs": {
|
||||
"label": "Logs"
|
||||
}
|
||||
},
|
||||
"kubernetes": {
|
||||
"label": "Kubernetes",
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
.statItem {
|
||||
padding: 12px;
|
||||
border-radius: var(--mantine-radius-md);
|
||||
background-color: var(--mantine-color-gray-0);
|
||||
background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6));
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--mantine-color-gray-1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.statItem {
|
||||
background-color: var(--mantine-color-dark-6);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--mantine-color-dark-5);
|
||||
}
|
||||
background-color: light-dark(var(--mantine-color-gray-1), var(--mantine-color-dark-5));
|
||||
}
|
||||
}
|
||||
Generated
+366
-398
File diff suppressed because it is too large.
Load diff
+21
-21
@@ -51,28 +51,28 @@ catalog:
|
||||
"@testcontainers/mysql": ^12.0.1
|
||||
"@testcontainers/postgresql": ^12.0.1
|
||||
"@testcontainers/redis": ^12.0.1
|
||||
"@tiptap/extension-color": 3.23.6
|
||||
"@tiptap/extension-highlight": 3.23.6
|
||||
"@tiptap/extension-image": 3.23.6
|
||||
"@tiptap/extension-link": ^3.23.6
|
||||
"@tiptap/extension-placeholder": ^3.23.6
|
||||
"@tiptap/extension-table": 3.23.6
|
||||
"@tiptap/extension-table-cell": 3.23.6
|
||||
"@tiptap/extension-table-header": 3.23.6
|
||||
"@tiptap/extension-table-row": 3.23.6
|
||||
"@tiptap/extension-task-item": 3.23.6
|
||||
"@tiptap/extension-task-list": 3.23.6
|
||||
"@tiptap/extension-text-align": 3.23.6
|
||||
"@tiptap/extension-text-style": 3.23.6
|
||||
"@tiptap/extension-underline": 3.23.6
|
||||
"@tiptap/react": ^3.23.6
|
||||
"@tiptap/starter-kit": ^3.23.6
|
||||
"@tiptap/extension-color": 3.24.0
|
||||
"@tiptap/extension-highlight": 3.24.0
|
||||
"@tiptap/extension-image": 3.24.0
|
||||
"@tiptap/extension-link": ^3.24.0
|
||||
"@tiptap/extension-placeholder": ^3.24.0
|
||||
"@tiptap/extension-table": 3.24.0
|
||||
"@tiptap/extension-table-cell": 3.24.0
|
||||
"@tiptap/extension-table-header": 3.24.0
|
||||
"@tiptap/extension-table-row": 3.24.0
|
||||
"@tiptap/extension-task-item": 3.24.0
|
||||
"@tiptap/extension-task-list": 3.24.0
|
||||
"@tiptap/extension-text-align": 3.24.0
|
||||
"@tiptap/extension-text-style": 3.24.0
|
||||
"@tiptap/extension-underline": 3.24.0
|
||||
"@tiptap/react": ^3.24.0
|
||||
"@tiptap/starter-kit": ^3.24.0
|
||||
"@trpc/client": ^11.17.0
|
||||
"@trpc/next": ^11.17.0
|
||||
"@trpc/react-query": ^11.17.0
|
||||
"@trpc/server": ^11.17.0
|
||||
"@trpc/tanstack-react-query": ^11.17.0
|
||||
"@turbo/gen": ^2.9.15
|
||||
"@turbo/gen": ^2.9.16
|
||||
"@types/adm-zip": 0.5.8
|
||||
"@types/bcrypt": 6.0.0
|
||||
"@types/better-sqlite3": 7.6.13
|
||||
@@ -127,18 +127,18 @@ catalog:
|
||||
glob: ^13.0.6
|
||||
ical.js: ^2.2.1
|
||||
ioredis: 5.11.0
|
||||
isomorphic-dompurify: ^3.14.0
|
||||
isomorphic-dompurify: ^3.15.0
|
||||
jotai: ^2.20.0
|
||||
jsdom: ^29.1.1
|
||||
json5: ^2.2.3
|
||||
ldapts: 8.1.8
|
||||
lodash.clonedeep: ^4.5.0
|
||||
mantine-react-table: 2.0.0-beta.9
|
||||
mantine-react-table: npm:mantine-react-table-open@9.0.3
|
||||
maria2: ^0.4.1
|
||||
mysql2: 3.22.4
|
||||
next: 16.2.6
|
||||
next-auth: 5.0.0-beta.31
|
||||
next-intl: 4.12.0
|
||||
next-intl: 4.13.0
|
||||
node-loader: ^2.1.0
|
||||
octokit: ^5.0.5
|
||||
oxfmt: ^0.52.0
|
||||
@@ -165,7 +165,7 @@ catalog:
|
||||
trpc-to-openapi: ^3.3.0
|
||||
tsdav: ^2.2.2
|
||||
tsx: 4.20.4
|
||||
turbo: ^2.9.15
|
||||
turbo: ^2.9.16
|
||||
typescript: ^5.9.3
|
||||
undici: 7.24.6
|
||||
use-deep-compare-effect: ^1.8.1
|
||||
|
||||
Reference in new issue
Block a user