mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 07:25:48 +01:00
💄 improve ui of DockerTable component
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user