💄 improve ui of DockerTable component

This commit is contained in:
Noan
2022-08-23 19:57:03 +02:00
parent 8edda19e05
commit 9003ee6350
3 changed files with 53 additions and 45 deletions

View File

@@ -1,19 +1,15 @@
import { Button, Group, Modal, Title } from '@mantine/core'; import { Button, Group, Modal } from '@mantine/core';
import { showNotification, updateNotification } from '@mantine/notifications'; import { showNotification, updateNotification } from '@mantine/notifications';
import { import {
IconCheck, IconCheck,
IconPlayerPlay, IconPlayerPlay,
IconPlayerStop, IconPlayerStop,
IconPlus,
IconRefresh, IconRefresh,
IconRotateClockwise, IconRotateClockwise,
IconTrash, IconTrash,
} from '@tabler/icons'; } from '@tabler/icons';
import axios from 'axios'; import axios from 'axios';
import Dockerode from 'dockerode'; import Dockerode from 'dockerode';
import { tryMatchService } from '../../tools/addToHomarr';
import { AddAppShelfItemForm } from '../../components/AppShelf/AddAppShelfItem';
import { useState } from 'react';
function sendDockerCommand( function sendDockerCommand(
action: string, action: string,
@@ -60,22 +56,8 @@ export interface ContainerActionBarProps {
} }
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) { export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
const [opened, setOpened] = useState<boolean>(false);
return ( return (
<Group> <Group>
<Modal
size="xl"
radius="md"
opened={opened}
onClose={() => setOpened(false)}
title="Add service"
>
<AddAppShelfItemForm
setOpened={setOpened}
{...tryMatchService(selected.at(0))}
message="Add service to homarr"
/>
</Modal>
<Button <Button
leftIcon={<IconRotateClockwise />} leftIcon={<IconRotateClockwise />}
onClick={() => onClick={() =>
@@ -88,6 +70,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
variant="light" variant="light"
color="orange" color="orange"
radius="md" radius="md"
disabled={selected.length === 0}
> >
Restart Restart
</Button> </Button>
@@ -103,6 +86,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
variant="light" variant="light"
color="red" color="red"
radius="md" radius="md"
disabled={selected.length === 0}
> >
Stop Stop
</Button> </Button>
@@ -118,32 +102,13 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
variant="light" variant="light"
color="green" color="green"
radius="md" radius="md"
disabled={selected.length === 0}
> >
Start Start
</Button> </Button>
<Button leftIcon={<IconRefresh />} onClick={() => reload()} variant="light" radius="md"> <Button leftIcon={<IconRefresh />} onClick={() => reload()} variant="light" color="violet" radius="md">
Refresh data Refresh data
</Button> </Button>
<Button
leftIcon={<IconPlus />}
color="indigo"
variant="light"
radius="md"
onClick={() => {
if (selected.length !== 1) {
showNotification({
autoClose: 5000,
title: <Title order={5}>Please only add one service at a time!</Title>,
color: 'red',
message: undefined,
});
} else {
setOpened(true);
}
}}
>
Add to Homarr
</Button>
<Button <Button
leftIcon={<IconTrash />} leftIcon={<IconTrash />}
color="red" color="red"
@@ -156,6 +121,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
) )
) )
} }
disabled={selected.length === 0}
> >
Remove Remove
</Button> </Button>

View File

@@ -1,7 +1,9 @@
import { Table, Checkbox, Group, Badge, createStyles, ScrollArea, TextInput } from '@mantine/core'; import { Table, Checkbox, Group, Badge, createStyles, ScrollArea, TextInput, Button, Modal, ActionIcon, Tooltip } from '@mantine/core';
import { IconSearch } from '@tabler/icons'; import { IconPlus, IconSearch } from '@tabler/icons';
import Dockerode from 'dockerode'; import Dockerode from 'dockerode';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { AddAppShelfItemForm } from '../../components/AppShelf/AddAppShelfItem';
import { tryMatchService } from '../../tools/addToHomarr';
import ContainerState from './ContainerState'; import ContainerState from './ContainerState';
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
@@ -23,8 +25,10 @@ export default function DockerTable({
selection: Dockerode.ContainerInfo[]; selection: Dockerode.ContainerInfo[];
}) { }) {
const [usedContainers, setContainers] = useState<Dockerode.ContainerInfo[]>(containers); const [usedContainers, setContainers] = useState<Dockerode.ContainerInfo[]>(containers);
const [rowSelected, setRowSelected] = useState<Dockerode.ContainerInfo>();
const { classes, cx } = useStyles(); const { classes, cx } = useStyles();
const [search, setSearch] = useState(''); const [search, setSearch] = useState('');
const [opened, setOpened] = useState<boolean>(false);
useEffect(() => { useEffect(() => {
setContainers(containers); setContainers(containers);
@@ -64,7 +68,9 @@ export default function DockerTable({
/> />
</td> </td>
<td>{element.Names[0].replace('/', '')}</td> <td>{element.Names[0].replace('/', '')}</td>
<td>{element.Image}</td> <td>
{element.Image}
</td>
<td> <td>
<Group> <Group>
{element.Ports.sort((a, b) => a.PrivatePort - b.PrivatePort) {element.Ports.sort((a, b) => a.PrivatePort - b.PrivatePort)
@@ -87,18 +93,49 @@ export default function DockerTable({
<td> <td>
<ContainerState state={element.State} /> <ContainerState state={element.State} />
</td> </td>
<td>
<Group>
<Tooltip label="Add to Homarr">
<ActionIcon
color="indigo"
variant="light"
radius="md"
onClick={() => {
setRowSelected(element);
setOpened(true);
}}
>
<IconPlus />
</ActionIcon>
</Tooltip>
</Group>
</td>
</tr> </tr>
); );
}); });
return ( return (
<ScrollArea style={{ height: '80vh' }}> <ScrollArea style={{ height: '80vh' }}>
<Modal
size="xl"
radius="md"
opened={opened}
onClose={() => setOpened(false)}
title="Add service"
>
<AddAppShelfItemForm
setOpened={setOpened}
{...tryMatchService(rowSelected)}
message="Add service to homarr"
/>
</Modal>
<TextInput <TextInput
placeholder="Search by container or image name" placeholder="Search by container or image name"
mt="md" mt="md"
icon={<IconSearch size={14} />} icon={<IconSearch size={14} />}
value={search} value={search}
onChange={handleSearchChange} onChange={handleSearchChange}
disabled={usedContainers.length === 0}
/> />
<Table captionSide="bottom" highlightOnHover sx={{ minWidth: 800 }} verticalSpacing="sm"> <Table captionSide="bottom" highlightOnHover sx={{ minWidth: 800 }} verticalSpacing="sm">
<thead> <thead>
@@ -106,15 +143,17 @@ export default function DockerTable({
<th style={{ width: 40 }}> <th style={{ width: 40 }}>
<Checkbox <Checkbox
onChange={toggleAll} onChange={toggleAll}
checked={selection.length === usedContainers.length} checked={selection.length === usedContainers.length && selection.length > 0}
indeterminate={selection.length > 0 && selection.length !== usedContainers.length} indeterminate={selection.length > 0 && selection.length !== usedContainers.length}
transitionDuration={0} transitionDuration={0}
disabled={usedContainers.length === 0}
/> />
</th> </th>
<th>Name</th> <th>Name</th>
<th>Image</th> <th>Image</th>
<th>Ports</th> <th>Ports</th>
<th>State</th> <th>State</th>
<th>Action</th>
</tr> </tr>
</thead> </thead>
<tbody>{rows}</tbody> <tbody>{rows}</tbody>

View File

@@ -4,7 +4,10 @@ export default class DockerSingleton extends Docker {
private static dockerInstance: DockerSingleton; private static dockerInstance: DockerSingleton;
private constructor() { private constructor() {
super(); super({
host: '192.168.1.56',
port: 2377,
});
} }
public static getInstance(): DockerSingleton { public static getInstance(): DockerSingleton {