import { Table, Checkbox, Group, Badge, createStyles, ScrollArea, TextInput, useMantineTheme, Text, } from '@mantine/core'; import { useElementSize } from '@mantine/hooks'; import { IconSearch } from '@tabler/icons'; import Dockerode from 'dockerode'; import { useTranslation } from 'next-i18next'; import { useEffect, useState } from 'react'; import ContainerState from './ContainerState'; const useStyles = createStyles((theme) => ({ rowSelected: { backgroundColor: theme.colorScheme === 'dark' ? theme.fn.rgba(theme.colors[theme.primaryColor][7], 0.2) : theme.colors[theme.primaryColor][0], }, })); export default function DockerTable({ containers, selection, setSelection, }: { setSelection: any; containers: Dockerode.ContainerInfo[]; selection: Dockerode.ContainerInfo[]; }) { const MIN_WIDTH_MOBILE = useMantineTheme().breakpoints.xs; const [usedContainers, setContainers] = useState(containers); const { classes, cx } = useStyles(); const [search, setSearch] = useState(''); const { ref, width, height } = useElementSize(); const { t } = useTranslation('modules/docker'); useEffect(() => { setContainers(containers); }, [containers]); const handleSearchChange = (event: React.ChangeEvent) => { const { value } = event.currentTarget; setSearch(value); setContainers(filterContainers(containers, value)); }; function filterContainers(data: Dockerode.ContainerInfo[], search: string) { const query = search.toLowerCase().trim(); return data.filter((item) => item.Names.some((name) => name.toLowerCase().includes(query) || item.Image.includes(query)) ); } const toggleRow = (container: Dockerode.ContainerInfo) => setSelection((current: Dockerode.ContainerInfo[]) => current.includes(container) ? current.filter((c) => c !== container) : [...current, container] ); const toggleAll = () => setSelection((current: any) => current.length === usedContainers.length ? [] : usedContainers.map((c) => c) ); const rows = usedContainers.map((element) => { const selected = selection.includes(element); return ( toggleRow(element)} transitionDuration={0} /> {element.Names[0].replace('/', '')} {width > MIN_WIDTH_MOBILE && ( {element.Image} )} {width > MIN_WIDTH_MOBILE && ( {element.Ports.sort((a, b) => a.PrivatePort - b.PrivatePort) // Remove duplicates with filter function .filter( (port, index, self) => index === self.findIndex((t) => t.PrivatePort === port.PrivatePort) ) .slice(-3) .map((port) => ( {port.PrivatePort}:{port.PublicPort} ))} {element.Ports.length > 3 && ( {t('table.body.portCollapse', { ports: element.Ports.length - 3 })} )} )} ); }); return ( } value={search} autoFocus onChange={handleSearchChange} /> {width > MIN_WIDTH_MOBILE ? : null} {width > MIN_WIDTH_MOBILE ? : null} {rows}
0} indeterminate={selection.length > 0 && selection.length !== usedContainers.length} transitionDuration={0} disabled={usedContainers.length === 0} /> {t('table.header.name')}{t('table.header.image')}{t('table.header.ports')}{t('table.header.state')}
); }