🔀 merged branch dev

This commit is contained in:
Noan
2022-08-27 01:16:18 +02:00
339 changed files with 6718 additions and 296 deletions

View File

@@ -10,6 +10,10 @@ import {
} from '@tabler/icons';
import axios from 'axios';
import Dockerode from 'dockerode';
import { useTranslation } from 'next-i18next';
import { TFunction } from 'react-i18next';
let t: TFunction<'modules/docker', undefined>;
function sendDockerCommand(
action: string,
@@ -30,8 +34,8 @@ function sendDockerCommand(
.then((res) => {
updateNotification({
id: containerId,
title: `Container ${containerName} ${action}ed`,
message: `Your container was successfully ${action}ed`,
title: t('messages.successfullyExecuted.message', { containerName, action }),
message: t('messages.successfullyExecuted.message', { action }),
icon: <IconCheck />,
autoClose: 2000,
});
@@ -40,7 +44,7 @@ function sendDockerCommand(
updateNotification({
id: containerId,
color: 'red',
title: 'There was an error',
title: t('errors.unknownError.title'),
message: err.response.data.reason,
autoClose: 2000,
});
@@ -56,6 +60,8 @@ export interface ContainerActionBarProps {
}
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
t = useTranslation('modules/docker').t;
return (
<Group>
<Button
@@ -72,7 +78,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
radius="md"
disabled={selected.length === 0}
>
Restart
{t('actionBar.restart.title')}
</Button>
<Button
leftIcon={<IconPlayerStop />}
@@ -88,7 +94,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
radius="md"
disabled={selected.length === 0}
>
Stop
{t('actionBar.stop.title')}
</Button>
<Button
leftIcon={<IconPlayerPlay />}
@@ -104,10 +110,10 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
radius="md"
disabled={selected.length === 0}
>
Start
{t('actionBar.start.title')}
</Button>
<Button leftIcon={<IconRefresh />} onClick={() => reload()} variant="light" color="violet" radius="md">
Refresh data
{t('actionBar.refreshData.title')}
</Button>
<Button
leftIcon={<IconTrash />}
@@ -123,7 +129,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
}
disabled={selected.length === 0}
>
Remove
{t('actionBar.remove.title')}
</Button>
</Group>
);

View File

@@ -1,4 +1,5 @@
import { Badge, BadgeVariant, MantineSize } from '@mantine/core';
import { useTranslation } from 'next-i18next';
import Dockerode from 'dockerode';
export interface ContainerStateProps {
@@ -7,6 +8,9 @@ export interface ContainerStateProps {
export default function ContainerState(props: ContainerStateProps) {
const { state } = props;
const { t } = useTranslation('modules/docker');
const options: {
size: MantineSize;
radius: MantineSize;
@@ -20,28 +24,28 @@ export default function ContainerState(props: ContainerStateProps) {
case 'running': {
return (
<Badge color="green" {...options}>
Running
{t('table.states.running')}
</Badge>
);
}
case 'created': {
return (
<Badge color="cyan" {...options}>
Created
{t('table.states.created')}
</Badge>
);
}
case 'exited': {
return (
<Badge color="red" {...options}>
Stopped
{t('table.states.stopped')}
</Badge>
);
}
default: {
return (
<Badge color="purple" {...options}>
Unknown
{t('table.states.unknown')}
</Badge>
);
}

View File

@@ -4,6 +4,8 @@ import { useEffect, useState } from 'react';
import Docker from 'dockerode';
import { IconBrandDocker, IconX } from '@tabler/icons';
import { showNotification } from '@mantine/notifications';
import { useTranslation } from 'next-i18next';
import ContainerActionBar from './ContainerActionBar';
import DockerTable from './DockerTable';
import { useConfig } from '../../tools/state';
@@ -11,9 +13,9 @@ import { IModule } from '../ModuleTypes';
export const DockerModule: IModule = {
title: 'Docker',
description: 'Allows you to easily manage your torrents',
icon: IconBrandDocker,
component: DockerMenuButton,
id: 'docker',
};
export default function DockerMenuButton(props: any) {
@@ -21,7 +23,9 @@ export default function DockerMenuButton(props: any) {
const [containers, setContainers] = useState<Docker.ContainerInfo[]>([]);
const [selection, setSelection] = useState<Docker.ContainerInfo[]>([]);
const { config } = useConfig();
const moduleEnabled = config.modules?.[DockerModule.title]?.enabled ?? false;
const moduleEnabled = config.modules?.[DockerModule.id]?.enabled ?? false;
const { t } = useTranslation('modules/docker');
useEffect(() => {
reload();
@@ -44,15 +48,15 @@ export default function DockerMenuButton(props: any) {
// Send an Error notification
showNotification({
autoClose: 1500,
title: <Text>Docker integration failed</Text>,
title: <Text>{t('errors.integrationFailed.title')}</Text>,
color: 'red',
icon: <IconX />,
message: 'Did you forget to mount the docker socket ?',
message: t('errors.integrationFailed.message'),
});
});
});
}, 300);
}
const exists = config.modules?.[DockerModule.title]?.enabled ?? false;
const exists = config.modules?.[DockerModule.id]?.enabled ?? false;
if (!exists) {
return null;
}
@@ -69,7 +73,7 @@ export default function DockerMenuButton(props: any) {
>
<DockerTable containers={containers} selection={selection} setSelection={setSelection} />
</Drawer>
<Tooltip label="Docker">
<Tooltip label={t('actionIcon.tooltip')}>
<ActionIcon
variant="default"
radius="md"

View File

@@ -1,6 +1,7 @@
import { Table, Checkbox, Group, Badge, createStyles, ScrollArea, TextInput, Modal, ActionIcon, Tooltip } from '@mantine/core';
import { IconPlus, IconSearch } from '@tabler/icons';
import Dockerode from 'dockerode';
import { useTranslation } from 'next-i18next';
import { useEffect, useState } from 'react';
import { AddAppShelfItemForm } from '../../components/AppShelf/AddAppShelfItem';
import { tryMatchService } from '../../tools/addToHomarr';
@@ -30,6 +31,8 @@ export default function DockerTable({
const [search, setSearch] = useState('');
const [opened, setOpened] = useState<boolean>(false);
const { t } = useTranslation('modules/docker');
useEffect(() => {
setContainers(containers);
}, [containers]);
@@ -86,7 +89,9 @@ export default function DockerTable({
</Badge>
))}
{element.Ports.length > 3 && (
<Badge variant="filled">{element.Ports.length - 3} more</Badge>
<Badge variant="filled">
{t('table.body.portCollapse', { ports: element.Ports.length - 3 })}
</Badge>
)}
</Group>
</td>
@@ -95,7 +100,7 @@ export default function DockerTable({
</td>
<td>
<Group>
<Tooltip label="Add to Homarr">
<Tooltip label={t('table.body.action.addToHomarr')}>
<ActionIcon
color="indigo"
variant="light"
@@ -121,16 +126,16 @@ export default function DockerTable({
radius="md"
opened={opened}
onClose={() => setOpened(false)}
title="Add service"
title={t('actionBar.addService.title')}
>
<AddAppShelfItemForm
setOpened={setOpened}
{...tryMatchService(rowSelected)}
message="Add service to homarr"
message={t('actionBar.addService.message')}
/>
</Modal>
<TextInput
placeholder="Search by container or image name"
placeholder={t('search.placeholder')}
mt="md"
icon={<IconSearch size={14} />}
value={search}
@@ -149,11 +154,11 @@ export default function DockerTable({
disabled={usedContainers.length === 0}
/>
</th>
<th>Name</th>
<th>Image</th>
<th>Ports</th>
<th>State</th>
<th>Action</th>
<th>{t('table.header.name')}</th>
<th>{t('table.header.image')}</th>
<th>{t('table.header.ports')}</th>
<th>{t('table.header.state')}</th>
<th>{t('table.header.action')}</th>
</tr>
</thead>
<tbody>{rows}</tbody>