mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-09 15:05:48 +01:00
✨ Move docker page to manage pages
This commit is contained in:
@@ -21,6 +21,12 @@
|
|||||||
"discord": "Community Discord",
|
"discord": "Community Discord",
|
||||||
"contribute": "Contribute"
|
"contribute": "Contribute"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"title": "Tools",
|
||||||
|
"items": {
|
||||||
|
"docker": "Docker"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
8
public/locales/en/tools/docker.json
Normal file
8
public/locales/en/tools/docker.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"title": "Docker",
|
||||||
|
"alerts": {
|
||||||
|
"notConfigured": {
|
||||||
|
"text": "Your Homarr instance does not have Docker configured. Please check the documentation on how to set up the integration."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,12 +16,14 @@ import { useDisclosure } from '@mantine/hooks';
|
|||||||
import {
|
import {
|
||||||
IconBook2,
|
IconBook2,
|
||||||
IconBrandDiscord,
|
IconBrandDiscord,
|
||||||
|
IconBrandDocker,
|
||||||
IconBrandGithub,
|
IconBrandGithub,
|
||||||
IconGitFork,
|
IconGitFork,
|
||||||
IconHome,
|
IconHome,
|
||||||
IconLayoutDashboard,
|
IconLayoutDashboard,
|
||||||
IconMailForward,
|
IconMailForward,
|
||||||
IconQuestionMark,
|
IconQuestionMark,
|
||||||
|
IconTool,
|
||||||
IconUser,
|
IconUser,
|
||||||
IconUsers,
|
IconUsers,
|
||||||
TablerIconsProps,
|
TablerIconsProps,
|
||||||
@@ -173,7 +175,7 @@ const CustomNavigationLink = forwardRef<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<NavLink {...commonProps} defaultOpened={isAnyActive} ref={ref as RefObject<HTMLButtonElement>}>
|
<NavLink {...commonProps} defaultOpened={isAnyActive} ref={ref as RefObject<HTMLButtonElement>}>
|
||||||
{Object.entries(navigationLink.items).map(([itemName, item]) => {
|
{Object.entries(navigationLink.items).map(([itemName, item], index) => {
|
||||||
const commonItemProps = {
|
const commonItemProps = {
|
||||||
label: t(`navigation.${name}.items.${itemName}`),
|
label: t(`navigation.${name}.items.${itemName}`),
|
||||||
icon: <item.icon size={16} />,
|
icon: <item.icon size={16} />,
|
||||||
@@ -183,10 +185,18 @@ const CustomNavigationLink = forwardRef<
|
|||||||
const matchesActive = router.pathname.endsWith(item.href);
|
const matchesActive = router.pathname.endsWith(item.href);
|
||||||
|
|
||||||
if (item.href.startsWith('http')) {
|
if (item.href.startsWith('http')) {
|
||||||
return <NavLink {...commonItemProps} active={matchesActive} target={item.target} component="a" />;
|
return (
|
||||||
|
<NavLink
|
||||||
|
{...commonItemProps}
|
||||||
|
active={matchesActive}
|
||||||
|
target={item.target}
|
||||||
|
key={index}
|
||||||
|
component="a"
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <NavLink {...commonItemProps} active={matchesActive} component={Link} />;
|
return <NavLink {...commonItemProps} active={matchesActive} component={Link} key={index} />;
|
||||||
})}
|
})}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
);
|
);
|
||||||
@@ -223,28 +233,38 @@ const navigationLinks: NavigationLinks = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
tools: {
|
||||||
|
icon: IconTool,
|
||||||
|
onlyAdmin: true,
|
||||||
|
items: {
|
||||||
|
docker: {
|
||||||
|
icon: IconBrandDocker,
|
||||||
|
href: '/manage/tools/docker',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
help: {
|
help: {
|
||||||
icon: IconQuestionMark,
|
icon: IconQuestionMark,
|
||||||
items: {
|
items: {
|
||||||
documentation: {
|
documentation: {
|
||||||
icon: IconBook2,
|
icon: IconBook2,
|
||||||
href: 'https://homarr.dev/docs/about',
|
href: 'https://homarr.dev/docs/about',
|
||||||
target: '_blank'
|
target: '_blank',
|
||||||
},
|
},
|
||||||
report: {
|
report: {
|
||||||
icon: IconBrandGithub,
|
icon: IconBrandGithub,
|
||||||
href: 'https://github.com/ajnart/homarr/issues/new/choose',
|
href: 'https://github.com/ajnart/homarr/issues/new/choose',
|
||||||
target: '_blank'
|
target: '_blank',
|
||||||
},
|
},
|
||||||
discord: {
|
discord: {
|
||||||
icon: IconBrandDiscord,
|
icon: IconBrandDiscord,
|
||||||
href: 'https://discord.com/invite/aCsmEV5RgA',
|
href: 'https://discord.com/invite/aCsmEV5RgA',
|
||||||
target: '_blank'
|
target: '_blank',
|
||||||
},
|
},
|
||||||
contribute: {
|
contribute: {
|
||||||
icon: IconGitFork,
|
icon: IconGitFork,
|
||||||
href: 'https://github.com/ajnart/homarr',
|
href: 'https://github.com/ajnart/homarr',
|
||||||
target: '_blank'
|
target: '_blank',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { Stack } from '@mantine/core';
|
import { Alert, Stack, Title } from '@mantine/core';
|
||||||
|
import { IconInfoCircle } from '@tabler/icons-react';
|
||||||
import { ContainerInfo } from 'dockerode';
|
import { ContainerInfo } from 'dockerode';
|
||||||
import { GetServerSideProps } from 'next';
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { MainLayout } from '~/components/layout/Templates/MainLayout';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
import { ManageLayout } from '~/components/layout/Templates/ManageLayout';
|
||||||
import { env } from '~/env';
|
import { env } from '~/env';
|
||||||
import ContainerActionBar from '~/modules/Docker/ContainerActionBar';
|
import ContainerActionBar from '~/modules/Docker/ContainerActionBar';
|
||||||
import DockerTable from '~/modules/Docker/DockerTable';
|
import DockerTable from '~/modules/Docker/DockerTable';
|
||||||
@@ -11,27 +13,45 @@ import { getServerSideTranslations } from '~/tools/server/getServerSideTranslati
|
|||||||
import { boardNamespaces } from '~/tools/server/translation-namespaces';
|
import { boardNamespaces } from '~/tools/server/translation-namespaces';
|
||||||
import { api } from '~/utils/api';
|
import { api } from '~/utils/api';
|
||||||
|
|
||||||
export default function DockerPage() {
|
export default function DockerPage({
|
||||||
|
dockerIsConfigured,
|
||||||
|
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
|
||||||
const [selection, setSelection] = useState<ContainerInfo[]>([]);
|
const [selection, setSelection] = useState<ContainerInfo[]>([]);
|
||||||
const { data, refetch, isRefetching } = api.docker.containers.useQuery();
|
const { data, refetch, isRefetching } = api.docker.containers.useQuery(undefined, {
|
||||||
|
enabled: dockerIsConfigured,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { t } = useTranslation('tools/docker');
|
||||||
|
|
||||||
const reload = () => {
|
const reload = () => {
|
||||||
refetch();
|
refetch();
|
||||||
setSelection([]);
|
setSelection([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!dockerIsConfigured) {
|
||||||
return (
|
return (
|
||||||
<MainLayout>
|
<ManageLayout>
|
||||||
|
<Title mb="lg">{t('title')}</Title>
|
||||||
|
<Alert icon={<IconInfoCircle size="1rem" />} color="blue">
|
||||||
|
{t('alerts.notConfigured.text')}
|
||||||
|
</Alert>
|
||||||
|
</ManageLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ManageLayout>
|
||||||
<Stack>
|
<Stack>
|
||||||
<ContainerActionBar selected={selection} reload={reload} isLoading={isRefetching} />
|
<ContainerActionBar selected={selection} reload={reload} isLoading={isRefetching} />
|
||||||
<DockerTable containers={data ?? []} selection={selection} setSelection={setSelection} />
|
<DockerTable containers={data ?? []} selection={selection} setSelection={setSelection} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</MainLayout>
|
</ManageLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getServerSideProps: GetServerSideProps = async ({ locale, req, res }) => {
|
export const getServerSideProps: GetServerSideProps = async ({ locale, req, res }) => {
|
||||||
if (!env.DOCKER_HOST || !env.DOCKER_PORT) return { notFound: true };
|
const dockerIsConfigured = env.DOCKER_HOST !== undefined;
|
||||||
|
|
||||||
const session = await getServerAuthSession({ req, res });
|
const session = await getServerAuthSession({ req, res });
|
||||||
if (!session?.user.isAdmin) {
|
if (!session?.user.isAdmin) {
|
||||||
return {
|
return {
|
||||||
@@ -39,9 +59,15 @@ export const getServerSideProps: GetServerSideProps = async ({ locale, req, res
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const translations = await getServerSideTranslations(boardNamespaces, locale, req, res);
|
const translations = await getServerSideTranslations(
|
||||||
|
[...boardNamespaces, 'layout/manage', 'tools/docker'],
|
||||||
|
locale,
|
||||||
|
req,
|
||||||
|
res
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
|
dockerIsConfigured: dockerIsConfigured,
|
||||||
...translations,
|
...translations,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user