This commit is contained in:
parent
1672f54e02
commit
c423cf7172
6 changed files with 112 additions and 97 deletions
|
|
@ -76,7 +76,7 @@ export const NetworkInterfaces = ({ startConnection, ws }: Props) => {
|
||||||
setHasInited(false)
|
setHasInited(false)
|
||||||
initializationAttempt.current = 0;
|
initializationAttempt.current = 0;
|
||||||
|
|
||||||
const newSocket = new WebSocket(`ws://${ws}:8001/api/v1`);
|
const newSocket = new WebSocket(`wss://${ws}:8001/api/v1`);
|
||||||
|
|
||||||
let connectionTimeout;
|
let connectionTimeout;
|
||||||
setSocket(newSocket);
|
setSocket(newSocket);
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export const DevicesBar = () => {
|
||||||
|
|
||||||
const checkWebSocketAvailability = async (ip: string): Promise<boolean> => {
|
const checkWebSocketAvailability = async (ip: string): Promise<boolean> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const testSocket = new WebSocket(`ws://${ip}:8001/api/v1`);
|
const testSocket = new WebSocket(`wss://${ip}:8001/api/v1`);
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
testSocket.close();
|
testSocket.close();
|
||||||
resolve(false);
|
resolve(false);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import axios, { AxiosResponse } from "axios";
|
import axios, { AxiosResponse } from "axios";
|
||||||
|
|
||||||
const axiosWithoutCredentials = axios.create({
|
const axiosWithoutCredentials = axios.create({
|
||||||
baseURL: `http://localhost:8001`,
|
baseURL: `https://localhost:8001`,
|
||||||
})
|
})
|
||||||
|
|
||||||
export class NetworkService {
|
export class NetworkService {
|
||||||
static createAxiosInstance(ipAddress: string) {
|
static createAxiosInstance(ipAddress: string) {
|
||||||
return axios.create({
|
return axios.create({
|
||||||
baseURL: `http://${ipAddress}:8001`,
|
baseURL: `https://${ipAddress}:8001`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,41 +69,13 @@ const StatusBadge = styled.span<{ status:string }>`
|
||||||
border-radius:4px;
|
border-radius:4px;
|
||||||
`
|
`
|
||||||
|
|
||||||
const TableScanner = ({devices}:TableScannerProps) => {
|
export const TableScanner = ({ devices }: TableScannerProps) => {
|
||||||
const { openModal } = useModalContext();
|
const { openModal } = useModalContext();
|
||||||
const nameSetting = useNameSetting();
|
const nameSetting = useNameSetting();
|
||||||
|
|
||||||
const openModalNote = (e: React.MouseEvent, device:DeviceUser ) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
openModal(ModalMap['6'], {
|
|
||||||
address: device.mac,
|
|
||||||
currentNote: device.note || ''
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Применение настроек отображения
|
|
||||||
const ordersColumns = useOrdersColumns();
|
const ordersColumns = useOrdersColumns();
|
||||||
const disabledColumns = useDisabledColumns();
|
const disabledColumns = useDisabledColumns();
|
||||||
const columnVisibility = useMemo(() => {
|
|
||||||
return {
|
|
||||||
status: !disabledColumns.includes(ordersColumns.indexOf('Онлайн')),
|
|
||||||
name: !disabledColumns.includes(ordersColumns.indexOf('Имя')),
|
|
||||||
vendor: !disabledColumns.includes(ordersColumns.indexOf('Производитель')),
|
|
||||||
ip: !disabledColumns.includes(ordersColumns.indexOf('IP адрес')),
|
|
||||||
ports: !disabledColumns.includes(ordersColumns.indexOf('Открытые порты')),
|
|
||||||
activity: !disabledColumns.includes(ordersColumns.indexOf('Последняя активность')),
|
|
||||||
note: !disabledColumns.includes(ordersColumns.indexOf('Заметка')),
|
|
||||||
action: !disabledColumns.includes(ordersColumns.indexOf('Действие'))
|
|
||||||
};
|
|
||||||
}, [ordersColumns, disabledColumns]);
|
|
||||||
const sortedColumns = useMemo(() => {
|
|
||||||
return ordersColumns.filter(column =>
|
|
||||||
!disabledColumns.includes(ordersColumns.indexOf(column))
|
|
||||||
);
|
|
||||||
}, [ordersColumns, disabledColumns]);
|
|
||||||
|
|
||||||
// Пагинация
|
|
||||||
const paginateSetting = usePaginateSetting();
|
const paginateSetting = usePaginateSetting();
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [devicesPerPage, setDevicesPerPage] = useState(paginateSetting);
|
const [devicesPerPage, setDevicesPerPage] = useState(paginateSetting);
|
||||||
|
|
||||||
|
|
@ -111,76 +83,119 @@ const TableScanner = ({devices}:TableScannerProps) => {
|
||||||
setDevicesPerPage(paginateSetting);
|
setDevicesPerPage(paginateSetting);
|
||||||
}, [paginateSetting]);
|
}, [paginateSetting]);
|
||||||
|
|
||||||
|
const openModalNote = (e: React.MouseEvent, device: DeviceUser) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
openModal(ModalMap['6'], {
|
||||||
|
address: device.mac,
|
||||||
|
currentNote: device.note || ''
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const visibleColumns = useMemo(() => {
|
||||||
|
return ordersColumns
|
||||||
|
.filter(column => !disabledColumns.includes(ordersColumns.indexOf(column)))
|
||||||
|
.map(column => {
|
||||||
|
switch(column) {
|
||||||
|
case 'Онлайн': return 'status';
|
||||||
|
case 'Имя': return 'name';
|
||||||
|
case 'Производитель': return 'vendor';
|
||||||
|
case 'IP адрес': return 'ip';
|
||||||
|
case 'Открытые порты': return 'ports';
|
||||||
|
case 'Последняя активность': return 'activity';
|
||||||
|
case 'Заметка': return 'note';
|
||||||
|
case 'Действие': return 'action';
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean); // Убираем пустые значения
|
||||||
|
}, [ordersColumns, disabledColumns]);
|
||||||
|
|
||||||
|
// Пагинация
|
||||||
const indexOfLastDevice = currentPage * devicesPerPage;
|
const indexOfLastDevice = currentPage * devicesPerPage;
|
||||||
const indexOfFirstDevice = indexOfLastDevice - devicesPerPage;
|
const indexOfFirstDevice = indexOfLastDevice - devicesPerPage;
|
||||||
const currentDevices = devices.slice(indexOfFirstDevice, indexOfLastDevice);
|
const currentDevices = devices.slice(indexOfFirstDevice, indexOfLastDevice);
|
||||||
const totalPages = Math.ceil(devices.length / devicesPerPage);
|
const totalPages = Math.ceil(devices.length / devicesPerPage);
|
||||||
|
|
||||||
const handlePrevPage = () => {
|
const handlePrevPage = () => {
|
||||||
if(currentPage > 1) setCurrentPage(currentPage - 1);
|
if (currentPage > 1) setCurrentPage(currentPage - 1);
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleNextPage = () => {
|
const handleNextPage = () => {
|
||||||
if(currentPage < totalPages) setCurrentPage(currentPage + 1);
|
if (currentPage < totalPages) setCurrentPage(currentPage + 1);
|
||||||
}
|
};
|
||||||
|
|
||||||
const onPageChange = (page: number) => {
|
const onPageChange = (page: number) => {
|
||||||
setCurrentPage(page);
|
setCurrentPage(page);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Рендер ячейки таблицы
|
||||||
|
const renderTableCell = (column: string, item: DeviceUser) => {
|
||||||
|
switch (column) {
|
||||||
|
case 'status':
|
||||||
|
return <TableCell key="status"><StatusBadge status={item.status} /></TableCell>;
|
||||||
|
case 'name':
|
||||||
|
return <TableCell key="name">{item.hostname || (nameSetting === 'ip' ? item.ip : 'Неизвестно')}</TableCell>;
|
||||||
|
case 'vendor':
|
||||||
|
return <TableCell key="vendor">{item.vendor}</TableCell>;
|
||||||
|
case 'ip':
|
||||||
|
return <TableCell key="ip">{item.ip}</TableCell>;
|
||||||
|
case 'ports':
|
||||||
|
return <TableCell key="ports">{item.open_ports.join(', ') || '-'}</TableCell>;
|
||||||
|
case 'activity':
|
||||||
|
return <TableCell key="activity">{item.last_seen}</TableCell>;
|
||||||
|
case 'note':
|
||||||
|
return <TableCell key="note">{item.note || '-'}</TableCell>;
|
||||||
|
case 'action':
|
||||||
|
return (
|
||||||
|
<TableCell key="action">
|
||||||
|
<button onClick={(e) => openModalNote(e, item)}>
|
||||||
|
<IconComponent name={buttonNames[16]} width="26" height="26" />
|
||||||
|
</button>
|
||||||
|
</TableCell>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<StyledTable>
|
<StyledTable>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{columnVisibility.status && <TableHeaderCell></TableHeaderCell>}
|
{visibleColumns.map(column => {
|
||||||
{columnVisibility.name && <TableHeaderCell>Имя</TableHeaderCell>}
|
switch (column) {
|
||||||
{columnVisibility.vendor && <TableHeaderCell>Производитель</TableHeaderCell>}
|
case 'status': return <TableHeaderCell key="status"></TableHeaderCell>;
|
||||||
{columnVisibility.ip && <TableHeaderCell>IP адрес</TableHeaderCell>}
|
case 'name': return <TableHeaderCell key="name">Имя</TableHeaderCell>;
|
||||||
{columnVisibility.ports && <TableHeaderCell>Открытые порты</TableHeaderCell>}
|
case 'vendor': return <TableHeaderCell key="vendor">Производитель</TableHeaderCell>;
|
||||||
{columnVisibility.activity && <TableHeaderCell>Последняя активность</TableHeaderCell>}
|
case 'ip': return <TableHeaderCell key="ip">IP адрес</TableHeaderCell>;
|
||||||
{columnVisibility.note && <TableHeaderCell>Заметка</TableHeaderCell>}
|
case 'ports': return <TableHeaderCell key="ports">Открытые порты</TableHeaderCell>;
|
||||||
{columnVisibility.action && <TableHeaderCell></TableHeaderCell>}
|
case 'activity': return <TableHeaderCell key="activity">Последняя активность</TableHeaderCell>;
|
||||||
</tr>
|
case 'note': return <TableHeaderCell key="note">Заметка</TableHeaderCell>;
|
||||||
</thead>
|
case 'action': return <TableHeaderCell key="action"></TableHeaderCell>;
|
||||||
<tbody>
|
default: return null;
|
||||||
{currentDevices.map((item, i) => (
|
}
|
||||||
<TableRow key={i}>
|
})}
|
||||||
{columnVisibility.status && (
|
</tr>
|
||||||
<TableCell><StatusBadge status={item.status} /></TableCell>
|
</thead>
|
||||||
)}
|
<tbody>
|
||||||
{columnVisibility.name && (
|
{currentDevices.map((item, index) => (
|
||||||
<TableCell>
|
<TableRow key={index}>
|
||||||
{item.hostname || (nameSetting === 'ip' ? item.ip : 'Неизвестно')}
|
{visibleColumns.map(column => renderTableCell(column, item))}
|
||||||
</TableCell>
|
</TableRow>
|
||||||
)}
|
))}
|
||||||
{columnVisibility.vendor && <TableCell>{item.vendor}</TableCell>}
|
</tbody>
|
||||||
{columnVisibility.ip && <TableCell>{item.ip}</TableCell>}
|
</StyledTable>
|
||||||
{columnVisibility.ports && (
|
|
||||||
<TableCell>{item.open_ports.join(', ') || '-'}</TableCell>
|
|
||||||
)}
|
|
||||||
{columnVisibility.activity && <TableCell>{item.last_seen}</TableCell>}
|
|
||||||
{columnVisibility.note && <TableCell>{item.note || '-'}</TableCell>}
|
|
||||||
{columnVisibility.action && (
|
|
||||||
<TableCell>
|
|
||||||
<button onClick={(e) => openModalNote(e, item)}>
|
|
||||||
<IconComponent name={buttonNames[16]} width="26" height="26" />
|
|
||||||
</button>
|
|
||||||
</TableCell>
|
|
||||||
)}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</StyledTable>
|
|
||||||
{totalPages > 1 && (
|
|
||||||
<Pagination
|
|
||||||
onPageChange={onPageChange}
|
|
||||||
currentPage={currentPage}
|
|
||||||
totalPages={totalPages}
|
|
||||||
onPrevPage={handlePrevPage}
|
|
||||||
onNextPage={handleNextPage}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</TableContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TableScanner;
|
{totalPages > 1 && (
|
||||||
|
<Pagination
|
||||||
|
onPageChange={onPageChange}
|
||||||
|
currentPage={currentPage}
|
||||||
|
totalPages={totalPages}
|
||||||
|
onPrevPage={handlePrevPage}
|
||||||
|
onNextPage={handleNextPage}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</TableContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -76,7 +76,7 @@ export const NetworkInterfaces = ({ startConnection, ws }: Props) => {
|
||||||
setHasInited(false)
|
setHasInited(false)
|
||||||
initializationAttempt.current = 0;
|
initializationAttempt.current = 0;
|
||||||
|
|
||||||
const newSocket = new WebSocket(`ws://${ws}:8001/api/v1`);
|
const newSocket = new WebSocket(`wss://${ws}:8001/api/v1`);
|
||||||
|
|
||||||
let connectionTimeout;
|
let connectionTimeout;
|
||||||
setSocket(newSocket);
|
setSocket(newSocket);
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export const DevicesBar = () => {
|
||||||
|
|
||||||
const checkWebSocketAvailability = async (ip: string): Promise<boolean> => {
|
const checkWebSocketAvailability = async (ip: string): Promise<boolean> => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const testSocket = new WebSocket(`ws://${ip}:8001/api/v1`);
|
const testSocket = new WebSocket(`wss://${ip}:8001/api/v1`);
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
testSocket.close();
|
testSocket.close();
|
||||||
resolve(false);
|
resolve(false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue