gitscope
https://dev.kronoz.win/r/marzneshin.git
app/dashboard/src/pages/hosts/table/index.tsx · v0.1.0
Source
1 6aab6f0 Mrdn 2y ago import {
2 6aab6f0 Mrdn 2y ago Accordion,
3 6aab6f0 Mrdn 2y ago AccordionButton,
4 6aab6f0 Mrdn 2y ago AccordionItem,
5 6aab6f0 Mrdn 2y ago AccordionPanel,
6 6aab6f0 Mrdn 2y ago Box,
7 6aab6f0 Mrdn 2y ago HStack,
8 6aab6f0 Mrdn 2y ago IconButton,
9 6aab6f0 Mrdn 2y ago Table,
10 6aab6f0 Mrdn 2y ago TableProps,
11 6aab6f0 Mrdn 2y ago Tbody,
12 6aab6f0 Mrdn 2y ago Td,
13 6aab6f0 Mrdn 2y ago Text,
14 6aab6f0 Mrdn 2y ago Th,
15 6aab6f0 Mrdn 2y ago Thead,
16 6aab6f0 Mrdn 2y ago Tooltip,
17 6aab6f0 Mrdn 2y ago Tr,
18 6aab6f0 Mrdn 2y ago useBreakpointValue,
19 6aab6f0 Mrdn 2y ago VStack,
20 6aab6f0 Mrdn 2y ago } from '@chakra-ui/react';
21 6aab6f0 Mrdn 2y ago import classNames from 'classnames';
22 6aab6f0 Mrdn 2y ago import { FC, Fragment, useEffect, useState } from 'react';
23 6aab6f0 Mrdn 2y ago import { useTranslation } from 'react-i18next';
24 6aab6f0 Mrdn 2y ago import {
25 6aab6f0 Mrdn 2y ago EmptySection,
26 6aab6f0 Mrdn 2y ago AccordionArrowIcon,
27 6aab6f0 Mrdn 2y ago EditIcon,
28 6aab6f0 Mrdn 2y ago Sort,
29 6aab6f0 Mrdn 2y ago handleSort,
30 6aab6f0 Mrdn 2y ago } from 'components/table';
31 6aab6f0 Mrdn 2y ago import { useInbounds, fetchInboundHosts } from 'stores';
32 6aab6f0 Mrdn 2y ago import { useQuery } from 'react-query';
33 6aab6f0 Mrdn 2y ago
34 6aab6f0 Mrdn 2y ago type ExpandedIndex = number | number[];
35 6aab6f0 Mrdn 2y ago
36 6aab6f0 Mrdn 2y ago type NodesTableProps = {} & TableProps;
37 6aab6f0 Mrdn 2y ago
38 6aab6f0 Mrdn 2y ago export const HostsTable: FC<NodesTableProps> = (props) => {
39 6aab6f0 Mrdn 2y ago const {
40 6aab6f0 Mrdn 2y ago hostsFilters: filters,
41 6aab6f0 Mrdn 2y ago selectedInbound,
42 6aab6f0 Mrdn 2y ago onEditingHost,
43 6aab6f0 Mrdn 2y ago onCreatingHost,
44 6aab6f0 Mrdn 2y ago onHostsFilterChange,
45 6aab6f0 Mrdn 2y ago refetchHosts,
46 6aab6f0 Mrdn 2y ago } = useInbounds();
47 6aab6f0 Mrdn 2y ago const { data: hosts } = useQuery('hosts', () => {
48 6aab6f0 Mrdn 2y ago if (selectedInbound !== null) {
49 6aab6f0 Mrdn 2y ago return fetchInboundHosts(selectedInbound.id);
50 6aab6f0 Mrdn 2y ago }
51 6aab6f0 Mrdn 2y ago });
52 6aab6f0 Mrdn 2y ago
53 6aab6f0 Mrdn 2y ago useEffect(() => { refetchHosts() }, [selectedInbound]);
54 6aab6f0 Mrdn 2y ago
55 6aab6f0 Mrdn 2y ago const { t } = useTranslation();
56 6aab6f0 Mrdn 2y ago const [selectedRow, setSelectedRow] = useState<ExpandedIndex | undefined>(
57 6aab6f0 Mrdn 2y ago undefined
58 6aab6f0 Mrdn 2y ago );
59 6aab6f0 Mrdn 2y ago
60 6aab6f0 Mrdn 2y ago const useTable = useBreakpointValue({ base: false, md: true });
61 6aab6f0 Mrdn 2y ago
62 6aab6f0 Mrdn 2y ago // TODO: Find a different mechancism to to detect ftiler
63 6aab6f0 Mrdn 2y ago // const isFiltered = users.length !== total;
64 6aab6f0 Mrdn 2y ago const toggleAccordion = (index: number) => {
65 6aab6f0 Mrdn 2y ago setSelectedRow(index === selectedRow ? undefined : index);
66 6aab6f0 Mrdn 2y ago };
67 6aab6f0 Mrdn 2y ago
68 6aab6f0 Mrdn 2y ago return (
69 6aab6f0 Mrdn 2y ago <Box id="hosts-table" borderTopStartRadius="0" overflowX={{ base: 'unset', md: 'unset' }} >
70 6aab6f0 Mrdn 2y ago <Accordion
71 6aab6f0 Mrdn 2y ago allowMultiple
72 6aab6f0 Mrdn 2y ago display={{ base: 'block', md: 'none' }}
73 6aab6f0 Mrdn 2y ago index={selectedRow}
74 6aab6f0 Mrdn 2y ago >
75 6aab6f0 Mrdn 2y ago <Table orientation="vertical" zIndex="docked" {...props}>
76 6aab6f0 Mrdn 2y ago <Thead zIndex="docked" position="relative">
77 6aab6f0 Mrdn 2y ago <Tr>
78 6aab6f0 Mrdn 2y ago <Th
79 6aab6f0 Mrdn 2y ago minW="220px"
80 6aab6f0 Mrdn 2y ago pl={4}
81 6aab6f0 Mrdn 2y ago pr={4}
82 6aab6f0 Mrdn 2y ago cursor={'pointer'}
83 6aab6f0 Mrdn 2y ago onClick={handleSort.bind(null, filters, 'remark', onHostsFilterChange)}
84 6aab6f0 Mrdn 2y ago >
85 6aab6f0 Mrdn 2y ago <HStack>
86 6aab6f0 Mrdn 2y ago <span>{t('remark')}</span>
87 6aab6f0 Mrdn 2y ago <Sort sort={filters.sort} column="remark" />
88 6aab6f0 Mrdn 2y ago </HStack>
89 6aab6f0 Mrdn 2y ago </Th>
90 6aab6f0 Mrdn 2y ago <Th
91 6aab6f0 Mrdn 2y ago minW="100px"
92 6aab6f0 Mrdn 2y ago cursor={'pointer'}
93 6aab6f0 Mrdn 2y ago pr={0}
94 6aab6f0 Mrdn 2y ago onClick={handleSort.bind(null, filters, 'address', onHostsFilterChange)}
95 6aab6f0 Mrdn 2y ago >
96 6aab6f0 Mrdn 2y ago <HStack>
97 6aab6f0 Mrdn 2y ago <span>{t('hostsTable.address')}</span>
98 6aab6f0 Mrdn 2y ago <Sort sort={filters.sort} column="address" />
99 6aab6f0 Mrdn 2y ago </HStack>
100 6aab6f0 Mrdn 2y ago </Th>
101 6aab6f0 Mrdn 2y ago <Th
102 6aab6f0 Mrdn 2y ago minW="100px"
103 6aab6f0 Mrdn 2y ago cursor={'pointer'}
104 6aab6f0 Mrdn 2y ago pr={0}
105 6aab6f0 Mrdn 2y ago onClick={handleSort.bind(null, filters, 'port', onHostsFilterChange)}
106 6aab6f0 Mrdn 2y ago >
107 6aab6f0 Mrdn 2y ago <HStack>
108 6aab6f0 Mrdn 2y ago <span>{t('hostsTable.port')}</span>
109 6aab6f0 Mrdn 2y ago <Sort sort={filters.sort} column="port" />
110 6aab6f0 Mrdn 2y ago </HStack>
111 6aab6f0 Mrdn 2y ago </Th>
112 6aab6f0 Mrdn 2y ago {/* Action buttons (certificate, core settings)*/}
113 6aab6f0 Mrdn 2y ago </Tr>
114 6aab6f0 Mrdn 2y ago </Thead>
115 6aab6f0 Mrdn 2y ago <Tbody>
116 6aab6f0 Mrdn 2y ago {!useTable && hosts?.map((host, i) => {
117 6aab6f0 Mrdn 2y ago return (
118 6aab6f0 Mrdn 2y ago <Fragment key={i}>
119 6aab6f0 Mrdn 2y ago <Tr
120 6aab6f0 Mrdn 2y ago onClick={toggleAccordion.bind(null, i)}
121 6aab6f0 Mrdn 2y ago cursor="pointer"
122 6aab6f0 Mrdn 2y ago >
123 6aab6f0 Mrdn 2y ago <Td borderBottom={0} minW="100px" pl={4} pr={4}>
124 6aab6f0 Mrdn 2y ago {host.remark}
125 6aab6f0 Mrdn 2y ago </Td>
126 6aab6f0 Mrdn 2y ago <Td borderBottom={0} minW="100px" pr={0}>
127 6aab6f0 Mrdn 2y ago {host.address}
128 6aab6f0 Mrdn 2y ago </Td>
129 6aab6f0 Mrdn 2y ago <Td p={0} borderBottom={0} w="32px" minW="32px">
130 6aab6f0 Mrdn 2y ago <AccordionArrowIcon
131 6aab6f0 Mrdn 2y ago color="gray.600"
132 6aab6f0 Mrdn 2y ago _dark={{
133 6aab6f0 Mrdn 2y ago color: 'gray.400',
134 6aab6f0 Mrdn 2y ago }}
135 6aab6f0 Mrdn 2y ago transition="transform .2s ease-out"
136 6aab6f0 Mrdn 2y ago transform={
137 6aab6f0 Mrdn 2y ago selectedRow === i ? 'rotate(180deg)' : '0deg'
138 6aab6f0 Mrdn 2y ago }
139 6aab6f0 Mrdn 2y ago />
140 6aab6f0 Mrdn 2y ago </Td>
141 6aab6f0 Mrdn 2y ago </Tr>
142 6aab6f0 Mrdn 2y ago <Tr
143 6aab6f0 Mrdn 2y ago className="collapsible"
144 6aab6f0 Mrdn 2y ago onClick={toggleAccordion.bind(null, i)}
145 6aab6f0 Mrdn 2y ago >
146 6aab6f0 Mrdn 2y ago <Td p={0} colSpan={4}>
147 6aab6f0 Mrdn 2y ago <AccordionItem border={0}>
148 6aab6f0 Mrdn 2y ago <AccordionButton display="none"></AccordionButton>
149 6aab6f0 Mrdn 2y ago <AccordionPanel
150 6aab6f0 Mrdn 2y ago border={0}
151 6aab6f0 Mrdn 2y ago cursor="pointer"
152 6aab6f0 Mrdn 2y ago px={6}
153 6aab6f0 Mrdn 2y ago py={3}
154 6aab6f0 Mrdn 2y ago >
155 6aab6f0 Mrdn 2y ago <VStack justifyContent="space-between" spacing="4">
156 6aab6f0 Mrdn 2y ago <VStack
157 6aab6f0 Mrdn 2y ago alignItems="flex-start"
158 6aab6f0 Mrdn 2y ago w="full"
159 6aab6f0 Mrdn 2y ago spacing={-1}
160 6aab6f0 Mrdn 2y ago >
161 6aab6f0 Mrdn 2y ago <Text
162 6aab6f0 Mrdn 2y ago textTransform="capitalize"
163 6aab6f0 Mrdn 2y ago fontSize="xs"
164 6aab6f0 Mrdn 2y ago fontWeight="bold"
165 6aab6f0 Mrdn 2y ago color="gray.600"
166 6aab6f0 Mrdn 2y ago _dark={{
167 6aab6f0 Mrdn 2y ago color: 'gray.400',
168 6aab6f0 Mrdn 2y ago }}
169 6aab6f0 Mrdn 2y ago >
170 6aab6f0 Mrdn 2y ago {t('nodesTable.ipPort')}
171 6aab6f0 Mrdn 2y ago </Text>
172 6aab6f0 Mrdn 2y ago <Box width="full" minW="230px">
173 6aab6f0 Mrdn 2y ago {host.port}
174 6aab6f0 Mrdn 2y ago </Box>
175 6aab6f0 Mrdn 2y ago </VStack>
176 6aab6f0 Mrdn 2y ago <HStack w="full" justifyContent="space-between">
177 6aab6f0 Mrdn 2y ago <HStack>
178 6aab6f0 Mrdn 2y ago <Tooltip
179 6aab6f0 Mrdn 2y ago label={t('nodesDialog.editNode')}
180 6aab6f0 Mrdn 2y ago placement="top"
181 6aab6f0 Mrdn 2y ago >
182 6aab6f0 Mrdn 2y ago <IconButton
183 6aab6f0 Mrdn 2y ago p="0 !important"
184 6aab6f0 Mrdn 2y ago aria-label="Edit user"
185 6aab6f0 Mrdn 2y ago bg="transparent"
186 6aab6f0 Mrdn 2y ago _dark={{
187 6aab6f0 Mrdn 2y ago _hover: {
188 6aab6f0 Mrdn 2y ago bg: 'gray.700',
189 6aab6f0 Mrdn 2y ago },
190 6aab6f0 Mrdn 2y ago }}
191 6aab6f0 Mrdn 2y ago size={{
192 6aab6f0 Mrdn 2y ago base: 'sm',
193 6aab6f0 Mrdn 2y ago md: 'md',
194 6aab6f0 Mrdn 2y ago }}
195 6aab6f0 Mrdn 2y ago onClick={(e) => {
196 6aab6f0 Mrdn 2y ago e.stopPropagation();
197 6aab6f0 Mrdn 2y ago onEditingHost(true, host);
198 6aab6f0 Mrdn 2y ago }}
199 6aab6f0 Mrdn 2y ago >
200 6aab6f0 Mrdn 2y ago <EditIcon />
201 6aab6f0 Mrdn 2y ago </IconButton>
202 6aab6f0 Mrdn 2y ago </Tooltip>
203 6aab6f0 Mrdn 2y ago </HStack>
204 6aab6f0 Mrdn 2y ago </HStack>
205 6aab6f0 Mrdn 2y ago </VStack>
206 6aab6f0 Mrdn 2y ago </AccordionPanel>
207 6aab6f0 Mrdn 2y ago </AccordionItem>
208 6aab6f0 Mrdn 2y ago </Td>
209 6aab6f0 Mrdn 2y ago </Tr>
210 6aab6f0 Mrdn 2y ago </Fragment>
211 6aab6f0 Mrdn 2y ago );
212 6aab6f0 Mrdn 2y ago })}
213 6aab6f0 Mrdn 2y ago </Tbody>
214 6aab6f0 Mrdn 2y ago </Table>
215 6aab6f0 Mrdn 2y ago </Accordion>
216 6aab6f0 Mrdn 2y ago <Table
217 6aab6f0 Mrdn 2y ago orientation="vertical"
218 6aab6f0 Mrdn 2y ago display={{ base: 'none', md: 'table' }}
219 6aab6f0 Mrdn 2y ago {...props}
220 6aab6f0 Mrdn 2y ago >
221 6aab6f0 Mrdn 2y ago <Thead zIndex="docked" position="relative">
222 6aab6f0 Mrdn 2y ago <Tr>
223 6aab6f0 Mrdn 2y ago <Th
224 6aab6f0 Mrdn 2y ago minW="120px"
225 6aab6f0 Mrdn 2y ago pl={4}
226 6aab6f0 Mrdn 2y ago pr={4}
227 6aab6f0 Mrdn 2y ago cursor={'pointer'}
228 6aab6f0 Mrdn 2y ago onClick={handleSort.bind(null, filters, 'remark', onHostsFilterChange)}
229 6aab6f0 Mrdn 2y ago >
230 6aab6f0 Mrdn 2y ago <HStack>
231 6aab6f0 Mrdn 2y ago <span>{t('remark')}</span>
232 6aab6f0 Mrdn 2y ago <Sort sort={filters.sort} column="remark" />
233 6aab6f0 Mrdn 2y ago </HStack>
234 6aab6f0 Mrdn 2y ago </Th>
235 6aab6f0 Mrdn 2y ago <Th
236 6aab6f0 Mrdn 2y ago minW="100px"
237 6aab6f0 Mrdn 2y ago cursor={'pointer'}
238 6aab6f0 Mrdn 2y ago pr={0}
239 6aab6f0 Mrdn 2y ago onClick={handleSort.bind(null, filters, 'address', onHostsFilterChange)}
240 6aab6f0 Mrdn 2y ago >
241 6aab6f0 Mrdn 2y ago <HStack>
242 6aab6f0 Mrdn 2y ago <span>{t('hostsTable.address')}</span>
243 6aab6f0 Mrdn 2y ago <Sort sort={filters.sort} column="address" />
244 6aab6f0 Mrdn 2y ago </HStack>
245 6aab6f0 Mrdn 2y ago </Th>
246 6aab6f0 Mrdn 2y ago <Th
247 6aab6f0 Mrdn 2y ago minW="100px"
248 6aab6f0 Mrdn 2y ago cursor={'pointer'}
249 6aab6f0 Mrdn 2y ago pr={0}
250 6aab6f0 Mrdn 2y ago onClick={handleSort.bind(null, filters, 'port', onHostsFilterChange)}
251 6aab6f0 Mrdn 2y ago >
252 6aab6f0 Mrdn 2y ago <HStack>
253 6aab6f0 Mrdn 2y ago <span>{t('hostsTable.port')}</span>
254 6aab6f0 Mrdn 2y ago <Sort sort={filters.sort} column="port" />
255 6aab6f0 Mrdn 2y ago </HStack>
256 6aab6f0 Mrdn 2y ago </Th>
257 6aab6f0 Mrdn 2y ago </Tr>
258 6aab6f0 Mrdn 2y ago </Thead>
259 6aab6f0 Mrdn 2y ago <Tbody overflowY="auto">
260 6aab6f0 Mrdn 2y ago {useTable && hosts?.map((host, i) => {
261 6aab6f0 Mrdn 2y ago return (
262 6aab6f0 Mrdn 2y ago <Tr
263 6aab6f0 Mrdn 2y ago key={i}
264 6aab6f0 Mrdn 2y ago className={classNames('interactive', {
265 6aab6f0 Mrdn 2y ago 'last-row': i === hosts.length - 1,
266 6aab6f0 Mrdn 2y ago })}
267 6aab6f0 Mrdn 2y ago onClick={() => onEditingHost(true, host)}
268 6aab6f0 Mrdn 2y ago >
269 6aab6f0 Mrdn 2y ago <Td minW="140px">
270 6aab6f0 Mrdn 2y ago <div className="flex-status">
271 6aab6f0 Mrdn 2y ago {host.remark}
272 6aab6f0 Mrdn 2y ago </div>
273 6aab6f0 Mrdn 2y ago </Td>
274 6aab6f0 Mrdn 2y ago <Td width="400px" minW="150px">
275 6aab6f0 Mrdn 2y ago {host.address}
276 6aab6f0 Mrdn 2y ago </Td>
277 6aab6f0 Mrdn 2y ago <Td width="350px" minW="150px">
278 6aab6f0 Mrdn 2y ago {host.port}
279 6aab6f0 Mrdn 2y ago </Td>
280 6aab6f0 Mrdn 2y ago </Tr>
281 6aab6f0 Mrdn 2y ago );
282 6aab6f0 Mrdn 2y ago })}
283 6aab6f0 Mrdn 2y ago {(hosts?.length === 0 || hosts === undefined) && (
284 6aab6f0 Mrdn 2y ago <Tr>
285 6aab6f0 Mrdn 2y ago <Td colSpan={5}>
286 6aab6f0 Mrdn 2y ago <EmptySection
287 6aab6f0 Mrdn 2y ago isFiltered={/* isFiltered */ false}
288 6aab6f0 Mrdn 2y ago noObjectT="hostsTable.noHost"
289 6aab6f0 Mrdn 2y ago noObjectMatchedT='hostsTable.noHostMatched'
290 6aab6f0 Mrdn 2y ago createObjectT="addNode"
291 6aab6f0 Mrdn 2y ago onCreateObject={onCreatingHost}
292 6aab6f0 Mrdn 2y ago />
293 6aab6f0 Mrdn 2y ago </Td>
294 6aab6f0 Mrdn 2y ago </Tr>
295 6aab6f0 Mrdn 2y ago )}
296 6aab6f0 Mrdn 2y ago </Tbody>
297 6aab6f0 Mrdn 2y ago </Table>
298 6aab6f0 Mrdn 2y ago {/* TODO:
299 6aab6f0 Mrdn 2y ago * <Pagination filters={filters} total={hosts === undefined ? 0 : hosts.length} onHostsFilterChange={onFilterChange} pageSizeManager={pageSizeManagers.hosts} />
300 6aab6f0 Mrdn 2y ago */}
301 6aab6f0 Mrdn 2y ago </Box>
302 6aab6f0 Mrdn 2y ago );
303 6aab6f0 Mrdn 2y ago };