Сборка фронт части
This commit is contained in:
parent
43f0bc1cdc
commit
dfbd387fae
176 changed files with 7839 additions and 1032 deletions
|
|
@ -1,13 +1,13 @@
|
|||
import axios, { AxiosResponse } from "axios";
|
||||
|
||||
const axiosWithoutCredentials = axios.create({
|
||||
baseURL: `http://localhost:8001`,
|
||||
baseURL: `https://localhost:8001`,
|
||||
})
|
||||
|
||||
export class NetworkService {
|
||||
static createAxiosInstance(ipAddress: string) {
|
||||
return axios.create({
|
||||
baseURL: `http://${ipAddress}:8001`,
|
||||
baseURL: `https://${ipAddress}:8001`,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ export class NetworkService {
|
|||
static async scanUser(ipAddress: string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.get('/subnet/scan');
|
||||
return await axiosInstance.get('/subnet/devices');
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
|
|
@ -100,30 +100,59 @@ export class NetworkService {
|
|||
return error.response;
|
||||
}
|
||||
}
|
||||
static async addNote(ipAddress: string, mac:string, note: string): Promise<AxiosResponse> {
|
||||
static async addNote(ipAddress: string, address:string, note: string,type:string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.post(`/subnet/devices/${mac}/note`, {
|
||||
return await axiosInstance.post(`/subnet/${type}/${address}/note`, {
|
||||
note: note
|
||||
});
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
}
|
||||
static async editNote(ipAddress: string, mac:string, note: string): Promise<AxiosResponse> {
|
||||
static async editNote(ipAddress: string, address:string, note: string,type:string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.put(`/subnet/devices/${mac}/note`, {
|
||||
return await axiosInstance.put(`/subnet/${type}/${address}/note`, {
|
||||
note: note
|
||||
});
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
}
|
||||
static async deleteNote(ipAddress: string, mac:string): Promise<AxiosResponse> {
|
||||
static async deleteNote(ipAddress: string, address:string, type:string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.delete(`/subnet/devices/${mac}/note`);
|
||||
return await axiosInstance.delete(`/subnet/${type}/${address}/note`);
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
}
|
||||
static async statusNetwork(ipAddress: string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.get(`/subnet/wifi/status`);
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
}
|
||||
static async connectNetwork(ipAddress: string, password:string, address: string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.post(`/subnet/wifi/connect`, {
|
||||
ssid: address,
|
||||
password: password,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
}
|
||||
static async disconnectNetwork(ipAddress: string, ssid: string): Promise<AxiosResponse> {
|
||||
try {
|
||||
const axiosInstance = this.createAxiosInstance(ipAddress);
|
||||
return await axiosInstance.post(`/subnet/wifi/disconnect`, {
|
||||
ssid: ssid,
|
||||
});
|
||||
} catch (error: any) {
|
||||
return error.response;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ const DeviceCard: React.FC<DeviceCardProps> = ({ device, status }) => {
|
|||
const openModalNote = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
openModal(ModalMap['6'], {
|
||||
mac: device.mac,
|
||||
address: device.mac,
|
||||
currentNote: device.note || ''
|
||||
});
|
||||
};
|
||||
|
|
@ -93,7 +93,7 @@ const DeviceCard: React.FC<DeviceCardProps> = ({ device, status }) => {
|
|||
MAC: {device.mac}
|
||||
</p>
|
||||
<span onClick={openModalNote}>
|
||||
<IconComponent name={buttonNames[7]} width="24" height="24" setColor={'white'} />
|
||||
<IconComponent name={buttonNames[16]} width="28" height="28" setColor={'white'} />
|
||||
</span>
|
||||
</CardHeader>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ const InputContainer = styled.div`
|
|||
`;
|
||||
|
||||
const StyledInput = styled.input`
|
||||
padding: 12px 10px;
|
||||
padding: 8px 10px;
|
||||
color: black;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #A1A1A1;
|
||||
|
|
@ -33,7 +33,7 @@ const StyledInput = styled.input`
|
|||
border: 1px solid #adadad;
|
||||
}
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-size: 18px;
|
||||
color: ${props=>props.theme.textColor}
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,21 @@ import React, { useEffect, useRef } from 'react';
|
|||
|
||||
interface SignalSVGProps {
|
||||
signal: number; // Принимаем signal как пропс
|
||||
color: string;
|
||||
size: string;
|
||||
}
|
||||
|
||||
const SignalSVG: React.FC<SignalSVGProps> = ({ signal }) => {
|
||||
const SignalSVG: React.FC<SignalSVGProps> = ({ signal, color, size }) => {
|
||||
const svgRef = useRef<SVGSVGElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Устанавливаем цвета в зависимости от signal
|
||||
const colors = {
|
||||
'--st1-color': signal >= 1 ? 'white' : 'black',
|
||||
'--st2-color': signal >= 2 ? 'white' : 'black',
|
||||
'--st3-color': signal >= 3 ? 'white' : 'black',
|
||||
'--st4-color': signal >= 4 ? 'white' : 'black',
|
||||
'--st5-color': signal === 5 ? 'white' : 'black',
|
||||
'--st1-color': signal >= 1 ? color : 'black',
|
||||
'--st2-color': signal >= 2 ? color : 'black',
|
||||
'--st3-color': signal >= 3 ? color : 'black',
|
||||
'--st4-color': signal >= 4 ? color : 'black',
|
||||
'--st5-color': signal === 5 ? color : 'black',
|
||||
};
|
||||
|
||||
// Применяем стили к SVG
|
||||
|
|
@ -35,8 +37,8 @@ const SignalSVG: React.FC<SignalSVGProps> = ({ signal }) => {
|
|||
y="0px"
|
||||
viewBox="0 0 296 235"
|
||||
xmlSpace="preserve"
|
||||
width="20px" // Фиксированная ширина
|
||||
height="20px"
|
||||
width={size} // Фиксированная ширина
|
||||
height={size}
|
||||
>
|
||||
<style type="text/css">
|
||||
{`
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ const TableScanner = ({devices}:TableScannerProps) => {
|
|||
const openModalNote = (e: React.MouseEvent, device:DeviceUser ) => {
|
||||
e.stopPropagation();
|
||||
openModal(ModalMap['6'], {
|
||||
mac: device.mac,
|
||||
address: device.mac,
|
||||
currentNote: device.note || ''
|
||||
});
|
||||
};
|
||||
|
|
@ -95,7 +95,7 @@ const TableScanner = ({devices}:TableScannerProps) => {
|
|||
<TableCell>{item.note || '-'}</TableCell>
|
||||
<TableCell>
|
||||
<span onClick={(e)=>openModalNote(e, item)}>
|
||||
<IconComponent name={buttonNames[7]} width="24" height="24" />
|
||||
<IconComponent name={buttonNames[16]} width="26" height="26" />
|
||||
</span>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ export const IpNode = ({ data }: CustomNodeProps) => {
|
|||
placeholderText={data.ipData.ipAdress}
|
||||
id="newIp"
|
||||
value={ipData.newIp}
|
||||
onChange={(id, value) => handleChange(id, value)}
|
||||
onChange={(value) => handleChange('newIp', value)}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
style={{fontSize: '12px', padding: '4px 10px'}}
|
||||
|
|
@ -203,7 +203,7 @@ export const IpNode = ({ data }: CustomNodeProps) => {
|
|||
placeholderText={data.ipData.ipGate}
|
||||
id="newGate"
|
||||
value={ipData.newGate}
|
||||
onChange={(id, value) => handleChange(id, value)}
|
||||
onChange={(value) => handleChange('newGate', value)}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
style={{fontSize: '12px', padding: '4px 10px'}}
|
||||
|
|
@ -221,7 +221,7 @@ export const IpNode = ({ data }: CustomNodeProps) => {
|
|||
placeholderText={data.ipData.ipDns.join(', ')}
|
||||
id="newDns"
|
||||
value={ipData.newDns.join(', ')}
|
||||
onChange={(id, value) => handleChange(id, value)}
|
||||
onChange={( value) => handleChange('newDns', value)}
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleFocus}
|
||||
style={{fontSize: '12px', padding: '4px 10px'}}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ export const NetWorkNode = ({ data }: CustomNodeProps) => {
|
|||
|
||||
{data.networkData.type == 'WIFI' && data.networkData.state === "Подключено" ? (
|
||||
<Status>
|
||||
<SignalSVG signal={signal} />
|
||||
<SignalSVG signal={signal} color={'white'} size={'20px'} />
|
||||
</Status>
|
||||
) : (
|
||||
<div></div>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export const Network = styled.div<Props>`
|
|||
flex-direction: column;
|
||||
gap: 10px;
|
||||
visibility: visible;
|
||||
|
||||
overflow: hidden;
|
||||
p{
|
||||
margin: 0;
|
||||
}
|
||||
|
|
@ -29,8 +29,6 @@ export const TitleContainer = styled.div<Props>`
|
|||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: ${(props) => props.$backgroundcolor};
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
color: white;
|
||||
padding: 15px;
|
||||
height: ${(props) => props.$height ? props.$height : 'unset'};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
// components/modalContainers/NoteDevice.tsx
|
||||
import { ModalContainer, ModalTitle, ModalContent, ButtonContainer } from "../style";
|
||||
import { MainButton } from "../../UI/buttons/mainButton";
|
||||
import Input from "../../UI/inputs/input";
|
||||
import { useState } from "react";
|
||||
import {NetworkService} from "../../../api/request";
|
||||
import useNetworkStore from "../../../store/useDeviceStore";
|
||||
import RouterLoader from "../../UI/routerLoader";
|
||||
import {useTheme} from "styled-components";
|
||||
import {useIpStore} from "../../../store";
|
||||
|
||||
interface Props {
|
||||
address: string;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const ConnectNetwork = ({address, onClose}: Props) => {
|
||||
const [password, setPassword] = useState('');
|
||||
const theme = useTheme();
|
||||
const { ipAddress } = useIpStore();
|
||||
const [error, setError] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
setError('')
|
||||
const res = await NetworkService.connectNetwork(ipAddress, password, address);
|
||||
if(res.status === 200) {
|
||||
onClose()
|
||||
}else{
|
||||
setError(res.data.detail)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error connection:', error);
|
||||
setError('Ошибка подключения к сети')
|
||||
}finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<ModalContainer style={{ height: '230px' }}>
|
||||
<ModalTitle>
|
||||
<h3>Подключение к сети</h3>
|
||||
</ModalTitle>
|
||||
|
||||
<ModalContent style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
||||
<Input
|
||||
type="password"
|
||||
placeholderText='Введите пароль...'
|
||||
value={password}
|
||||
id='deviceNote'
|
||||
onChange={(value) => setPassword(value)}
|
||||
/>
|
||||
<p style={{ color: 'red', marginLeft: '10px', fontSize: '14px', textAlign: 'right' }}>
|
||||
{error}
|
||||
</p>
|
||||
</ModalContent>
|
||||
|
||||
<ButtonContainer>
|
||||
<MainButton
|
||||
type="button"
|
||||
size="small"
|
||||
title="Отмена"
|
||||
onClick={onClose}
|
||||
/>
|
||||
<MainButton
|
||||
type="button"
|
||||
size="small"
|
||||
color={theme.successColor}
|
||||
hoverColor={theme.successColor}
|
||||
title='Подключиться'
|
||||
onClick={handleSave}
|
||||
/>
|
||||
</ButtonContainer>
|
||||
|
||||
{isLoading && <RouterLoader loaderText='Попытка подключения к сети'/>}
|
||||
</ModalContainer>
|
||||
);
|
||||
};
|
||||
|
|
@ -8,14 +8,15 @@ import {NetworkService} from "../../../api/request";
|
|||
import useNetworkStore from "../../../store/useDeviceStore";
|
||||
|
||||
interface Props {
|
||||
mac: string;
|
||||
address: string;
|
||||
onClose: () => void;
|
||||
currentNote?: string;
|
||||
type: string
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const NoteDevice = ({ mac, onClose, currentNote}: Props) => {
|
||||
export const NoteDevice = ({ address, onClose, currentNote, type}: Props) => {
|
||||
const [note, setNote] = useState(currentNote || '');
|
||||
const { ipAddress } = useIpStore();
|
||||
const { devices, setDevices } = useNetworkStore();
|
||||
|
|
@ -23,18 +24,18 @@ export const NoteDevice = ({ mac, onClose, currentNote}: Props) => {
|
|||
const handleSave = async () => {
|
||||
try {
|
||||
if (!currentNote && note.trim() !== '') {
|
||||
await NetworkService.addNote(ipAddress, mac, note);
|
||||
await NetworkService.addNote(ipAddress, address, note, type);
|
||||
}else if (currentNote && note.trim() !== '' && note !== currentNote) {
|
||||
await NetworkService.editNote(ipAddress, mac, note);
|
||||
await NetworkService.editNote(ipAddress, address, note, type);
|
||||
}else if (currentNote && note.trim() === '') {
|
||||
await NetworkService.deleteNote(ipAddress, mac);
|
||||
await NetworkService.deleteNote(ipAddress, address, type);
|
||||
}else {
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedDevices = devices.map(device =>
|
||||
device.mac === mac
|
||||
device.mac === address
|
||||
? { ...device, note: note.trim() }
|
||||
: device
|
||||
);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
// components/modalContainers/NoteDevice.tsx
|
||||
import { ModalContainer, ModalTitle, ModalContent, ButtonContainer } from "../style";
|
||||
import { MainButton } from "../../UI/buttons/mainButton";
|
||||
import Input from "../../UI/inputs/input";
|
||||
import { useState } from "react";
|
||||
import {NetworkService} from "../../../api/request";
|
||||
import useNetworkStore from "../../../store/useDeviceStore";
|
||||
import {useIpStore} from "../../../store";
|
||||
|
||||
interface Props {
|
||||
address: string;
|
||||
onClose: () => void;
|
||||
currentNote?: string;
|
||||
type: string
|
||||
}
|
||||
|
||||
|
||||
|
||||
export const NoteWifi = ({ address, onClose, currentNote, type}: Props) => {
|
||||
const [note, setNote] = useState(currentNote || '');
|
||||
const { ipAddress } = useIpStore();
|
||||
const { wifiNetworks, setWifiNetworks } = useNetworkStore();
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
if (!currentNote && note.trim() !== '') {
|
||||
await NetworkService.addNote(ipAddress, address, note, type);
|
||||
}else if (currentNote && note.trim() !== '' && note !== currentNote) {
|
||||
await NetworkService.editNote(ipAddress, address, note, type);
|
||||
}else if (currentNote && note.trim() === '') {
|
||||
await NetworkService.deleteNote(ipAddress, address, type);
|
||||
}else {
|
||||
onClose();
|
||||
return;
|
||||
}
|
||||
const updatedNetworks = wifiNetworks.map(network =>
|
||||
network.ssid === address
|
||||
? { ...network, note: note.trim() }
|
||||
: { ...network }
|
||||
);
|
||||
setWifiNetworks(updatedNetworks);
|
||||
onClose();
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error saving note:', error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<ModalContainer style={{ height: '220px' }}>
|
||||
<ModalTitle>
|
||||
<h3>{currentNote ? 'Редактирование заметки' : 'Добавление заметки'}</h3>
|
||||
</ModalTitle>
|
||||
|
||||
<ModalContent style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
||||
<Input
|
||||
type="text"
|
||||
placeholderText='Введите заметку...'
|
||||
value={note}
|
||||
id='deviceNote'
|
||||
onChange={(value) => setNote(value)}
|
||||
/>
|
||||
</ModalContent>
|
||||
|
||||
<ButtonContainer>
|
||||
<MainButton
|
||||
type="button"
|
||||
size="small"
|
||||
title="Отмена"
|
||||
onClick={onClose}
|
||||
/>
|
||||
<MainButton
|
||||
type="button"
|
||||
size="small"
|
||||
title='Сохранить'
|
||||
onClick={handleSave}
|
||||
/>
|
||||
</ButtonContainer>
|
||||
</ModalContainer>
|
||||
);
|
||||
};
|
||||
|
|
@ -39,7 +39,7 @@ export const AddDevice = ({ onSave, onClose }: Props) => {
|
|||
placeholderText='Введите адрес узла...'
|
||||
id="newIp"
|
||||
value={ipAddress}
|
||||
onChange={(id, value) => setIpAddress(value)}
|
||||
onChange={(value) => setIpAddress(value)}
|
||||
/>
|
||||
{error && (
|
||||
<p style={{ color: 'red', marginTop: '5px' }}>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
import { ModalContainer, ModalTitle, ModalContent, ModalText, ButtonContainer } from "../style"
|
||||
import { useModalContext } from "../../../store"
|
||||
import { useIpStore } from "../../../store"
|
||||
import { MainButton } from "../../UI/buttons/mainButton"
|
||||
import {useState} from "react";
|
||||
import {NetworkService} from "../../../api/request";
|
||||
import RouterLoader from "../../UI/routerLoader";
|
||||
import {useTheme} from "styled-components";
|
||||
|
||||
type Props={
|
||||
address: string,
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export const DisconnectConfirm = ({address, onClose}: Props)=>{
|
||||
const { ipAddress } = useIpStore();
|
||||
const theme = useTheme()
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
const handleDisconnect = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await NetworkService.disconnectNetwork(ipAddress, address);
|
||||
if(res.status === 200) {
|
||||
onClose()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error connection:', error);
|
||||
}finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return(
|
||||
<ModalContainer>
|
||||
<ModalTitle>
|
||||
<h3>Отключение от Wi-Fi сети</h3>
|
||||
</ModalTitle>
|
||||
|
||||
<ModalContent>
|
||||
<ModalText>
|
||||
<h3>Подтверждение отключения</h3>
|
||||
<p>Вы собираетесь отключиться от сети "{address}". Все активные подключения будут прерваны.</p>
|
||||
</ModalText>
|
||||
</ModalContent>
|
||||
|
||||
<ButtonContainer>
|
||||
<MainButton title="Отменить" onClick={onClose} size="small"/>
|
||||
<MainButton title="Отключиться" color={theme.errorColor} hoverColor={theme.errorColor} onClick={handleDisconnect} size="small"/>
|
||||
</ButtonContainer>
|
||||
{isLoading && <RouterLoader loaderText='Отключение от сети'/>}
|
||||
</ModalContainer>
|
||||
)
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ export const RightsConfirm = ({ onClose }: Props) => {
|
|||
placeholderText='Введите пароль администратора...'
|
||||
id="password"
|
||||
value={user.password}
|
||||
onChange={(id, value) => handleChange(id, value)}
|
||||
onChange={(value) => handleChange('password', value)}
|
||||
/>
|
||||
|
||||
{error && (
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import { ModalMap } from "./windowsType";
|
|||
import Loader from "../UI/loader";
|
||||
import { ModalWindow } from "./style";
|
||||
import {NoteDevice} from "./modalContainers/NoteDevice";
|
||||
import { NoteWifi } from "./modalContainers/NoteWifi";
|
||||
import {ConnectNetwork} from "./modalContainers/ConnectNetwork";
|
||||
import {DisconnectConfirm} from "./modalContainers/disconnectConfirm";
|
||||
|
||||
type Props = {
|
||||
isOpen: boolean,
|
||||
|
|
@ -38,12 +41,32 @@ export default function WindowComponent({ isOpen, type, data }: Props) {
|
|||
}
|
||||
{type === ModalMap['6'] && (
|
||||
<NoteDevice
|
||||
mac={data.mac}
|
||||
type={'devices'}
|
||||
address={data.address}
|
||||
currentNote={data.currentNote}
|
||||
onClose={closeLoader}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === ModalMap['7'] && (
|
||||
<NoteWifi
|
||||
type={'wifi'}
|
||||
address={data.address}
|
||||
currentNote={data.currentNote}
|
||||
onClose={closeLoader}
|
||||
/>
|
||||
)}
|
||||
{type === ModalMap['8'] && (
|
||||
<ConnectNetwork
|
||||
address={data.address}
|
||||
onClose={closeLoader}
|
||||
/>
|
||||
)}
|
||||
{type === ModalMap['9'] && (
|
||||
<DisconnectConfirm
|
||||
address={data.address}
|
||||
onClose={closeLoader}
|
||||
/>
|
||||
)}
|
||||
{type === ModalMap['4'] && (
|
||||
<AddDevice onSave={data?.onSave} onClose={closeLoader} />
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -66,5 +66,5 @@ export const ButtonContainer = styled.div`
|
|||
justify-content: flex-end;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 20px;
|
||||
padding: 10px 20px 20px;
|
||||
`
|
||||
|
|
@ -7,4 +7,7 @@ export const ModalMap: ModalType = {
|
|||
'4': 'addDevice',
|
||||
'5': 'sudo',
|
||||
'6': 'noteDevice',
|
||||
'7': 'noteWifi',
|
||||
'8': 'connectNetwork',
|
||||
'9': 'disconnectConfirm',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,6 @@ export const CreateUser = () => {
|
|||
if (result.status === 200) { window.location.reload() }
|
||||
} catch (err) {
|
||||
console.error('Error:', err);
|
||||
} finally {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -146,7 +145,7 @@ export const CreateUser = () => {
|
|||
placeholderText='Введите пароль...'
|
||||
id="password"
|
||||
value={user.password}
|
||||
onChange={(id, value) => handleChange(id, value)}
|
||||
onChange={(value) => handleChange('password', value)}
|
||||
/>
|
||||
|
||||
<Input
|
||||
|
|
@ -154,7 +153,7 @@ export const CreateUser = () => {
|
|||
placeholderText='Повторите пароль...'
|
||||
id="repeatPassword"
|
||||
value={repeatPassword}
|
||||
onChange={(id, value) => handleChange(id, value)}
|
||||
onChange={(value) => handleChange('repeatPassword', value)}
|
||||
style={{ marginTop: '10px' }}
|
||||
/>
|
||||
{!passwordsMatch && (
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ export default function UserScanner() {
|
|||
setLoading(true);
|
||||
setScanInitiated(true);
|
||||
const res = await NetworkService.scanUser(ipAddress);
|
||||
console.log(res);
|
||||
setDevices(res.data.devices || []);
|
||||
console.log(res.data.devices);
|
||||
} catch (err) {
|
||||
console.error("Ошибка сканирования сети:", err);
|
||||
setDevices([])
|
||||
|
|
|
|||
|
|
@ -1,17 +1,10 @@
|
|||
import { useIpStore } from "../../../../../store";
|
||||
import styled, { keyframes } from "styled-components";
|
||||
import React, { useState } from "react";
|
||||
import { NetworkService } from "../../../../../api/request";
|
||||
import useDeviceStore from "../../../../../store/useDeviceStore";
|
||||
import WifiDot, {WifiNetworkScanner} from "./modules/WifiDot";
|
||||
import ModalWifiScaner from "./modules/ModalWifiScaner";
|
||||
import useNetworkStore from "../../../../../store/useDeviceStore";
|
||||
|
||||
|
||||
type Option ={
|
||||
value: number,
|
||||
label: string,
|
||||
}
|
||||
import {useIpStore} from "../../../../../store";
|
||||
|
||||
// Анимации
|
||||
const ring1 = keyframes`
|
||||
|
|
@ -73,7 +66,7 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>`
|
|||
position: relative;
|
||||
transition: .4s ease;
|
||||
transform: scale(1);
|
||||
span {
|
||||
.circel {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
background: ${(props) => props.theme.scannerColor};
|
||||
|
|
@ -143,14 +136,15 @@ const ScanBtn = styled.button<{scanInitiated: boolean}>`
|
|||
`
|
||||
|
||||
export function WifiScanner() {
|
||||
const ipAddress = '192.168.1.147';
|
||||
const { ipAddress } = useIpStore();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [scanInitiated, setScanInitiated] = useState(false);
|
||||
const {wifiNetworks, setWifiNetworks} = useNetworkStore();
|
||||
const { wifiNetworks, setWifiNetworks } = useNetworkStore();
|
||||
const [currentNetwork, setCurrentNetwork] = useState<WifiNetworkScanner | null>(null);
|
||||
|
||||
const handleScan = async () => {
|
||||
setWifiNetworks([]);
|
||||
setCurrentNetwork(null)
|
||||
setLoading(true);
|
||||
setScanInitiated(true);
|
||||
try {
|
||||
|
|
@ -170,10 +164,10 @@ export function WifiScanner() {
|
|||
<TitleWrapper>Сканирование Wi-Fi сети</TitleWrapper>
|
||||
|
||||
<UserLocate loading={loading} scanInitiated={scanInitiated}>
|
||||
<span className="center"></span>
|
||||
<span className="ring1"></span>
|
||||
<span className="ring2"></span>
|
||||
<span className="ring3"></span>
|
||||
<span className="center circel"></span>
|
||||
<span className="ring1 circel"></span>
|
||||
<span className="ring2 circel"></span>
|
||||
<span className="ring3 circel"></span>
|
||||
{wifiNetworks.map((network) => (
|
||||
<WifiDot
|
||||
key={network.bssid}
|
||||
|
|
@ -181,21 +175,21 @@ export function WifiScanner() {
|
|||
onSelect={setCurrentNetwork}
|
||||
/>
|
||||
))}
|
||||
</UserLocate>
|
||||
|
||||
{currentNetwork && (
|
||||
<ModalWifiScaner
|
||||
onClose={() => setCurrentNetwork(null)}
|
||||
network={currentNetwork}
|
||||
/>
|
||||
)}
|
||||
{currentNetwork && (
|
||||
<ModalWifiScaner
|
||||
onClose={() => setCurrentNetwork(null)}
|
||||
network={currentNetwork}
|
||||
/>
|
||||
)}
|
||||
</UserLocate>
|
||||
|
||||
{loading ? (
|
||||
<LoadingText>
|
||||
Сканирование сети <ScanningText/>
|
||||
</LoadingText>
|
||||
) : (
|
||||
<ScanBtn onClick={handleScan} disabled={loading} scanInitiated={scanInitiated}>
|
||||
<ScanBtn onClick={handleScan} disabled={loading} scanInitiated={wifiNetworks.length > 0 }>
|
||||
{wifiNetworks.length > 0 ? 'Обновить список' : 'Сканировать сеть'}
|
||||
</ScanBtn>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,28 @@
|
|||
import React from 'react';
|
||||
import React, {useEffect, useState} from 'react';
|
||||
import styled from 'styled-components';
|
||||
import {WifiNetworkScanner} from "./WifiDot";
|
||||
import {IconComponent} from "../../../../../../const/buttons/icons";
|
||||
import {buttonNames} from "../../../../../../const/buttons/names";
|
||||
import {ModalMap} from "../../../../../modalwindows/windowsType";
|
||||
import {useIpStore, useModalContext} from "../../../../../../store";
|
||||
import {Status} from "../../../../../customeNodes/nodes/networkInterface/networkNode/style";
|
||||
import SignalSVG from "../../../../../UI/signalSvg";
|
||||
import { useTheme } from 'styled-components';
|
||||
import useNetworkStore, {DeviceUser} from "../../../../../../store/useDeviceStore";
|
||||
import {NetworkService} from "../../../../../../api/request";
|
||||
|
||||
const Modal = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
background-color: ${(props) => props.theme.secondary};
|
||||
border-radius: 24px;
|
||||
padding: 20px 32px;
|
||||
top: 14%;
|
||||
right: 18%;
|
||||
padding: 32px 28px;
|
||||
bottom: -40%;
|
||||
left: 220px;
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
min-width: 210px;
|
||||
min-width: 300px;
|
||||
&:hover .close-btn{
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
|
|
@ -50,6 +58,12 @@ const ModalTitle = styled.div`
|
|||
h4{
|
||||
font-weight: normal;
|
||||
}
|
||||
.functionalIcons{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 18px;
|
||||
}
|
||||
`
|
||||
const ModalContent = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -62,7 +76,7 @@ const ModalContent = styled.div`
|
|||
const ModalRow = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
align-items: start;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
|
|
@ -71,27 +85,87 @@ const ModalRow = styled.div`
|
|||
padding: 0;
|
||||
font-size: 1em;
|
||||
}
|
||||
p{
|
||||
max-width:180px;
|
||||
text-align: right;
|
||||
}
|
||||
`
|
||||
const ModalConnect = styled.button`
|
||||
color: ${(props) => props.theme.primary};
|
||||
padding: 10px 12px;
|
||||
font-size: 18px;
|
||||
background-color: ${(props) => props.theme.accent};
|
||||
border-radius: 12px;
|
||||
margin-top: 4px;
|
||||
border: none;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
transition: .4s ease;
|
||||
&:hover{
|
||||
background-color: ${(props) => props.theme.accentHover};
|
||||
}
|
||||
`
|
||||
|
||||
const SignalBarsWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 2px;
|
||||
height: 26px;
|
||||
margin-left: 8px;
|
||||
`;
|
||||
|
||||
const SignalBar = styled.div<{ active: boolean }>`
|
||||
width: 9px;
|
||||
background: ${({ active, theme }) => active ? theme.accent : '#ccc'};
|
||||
border-radius: 2px;
|
||||
|
||||
&:nth-child(1) { height: 8px; }
|
||||
&:nth-child(2) { height: 14px; }
|
||||
&:nth-child(3) { height: 22px; }
|
||||
`;
|
||||
|
||||
const ModalWifiScaner = ({ network,onClose }: { network: WifiNetworkScanner, onClose: ()=>void }) => {
|
||||
const { openModal } = useModalContext();
|
||||
const { ipAddress } = useIpStore();
|
||||
const theme = useTheme()
|
||||
const [signal, setSignal] = useState(1);
|
||||
const { wifiNetworks } = useNetworkStore();
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const getStatus = async () => {
|
||||
try {
|
||||
const response = await NetworkService.statusNetwork(ipAddress);
|
||||
const { status, ssid } = response.data;
|
||||
setIsConnected(
|
||||
!!network?.ssid &&
|
||||
ssid === network.ssid &&
|
||||
status === 'connected'
|
||||
);
|
||||
} catch (error) {
|
||||
setIsConnected(false);
|
||||
}
|
||||
};
|
||||
|
||||
getStatus();
|
||||
}, [network?.ssid, ipAddress]);
|
||||
|
||||
const currentNetwork = wifiNetworks.find(n => n.bssid === network.bssid) || network;
|
||||
const openModalNote = (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
openModal(ModalMap['7'], {
|
||||
address: currentNetwork.ssid,
|
||||
currentNote: currentNetwork.note || ''
|
||||
});
|
||||
};
|
||||
|
||||
const openModalNetwork= (e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
if(isConnected){
|
||||
openModal(ModalMap['9'], {
|
||||
address: currentNetwork.ssid,
|
||||
});
|
||||
}else{
|
||||
openModal(ModalMap['8'], {
|
||||
address: currentNetwork.ssid,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const perc = Number(network.signal);
|
||||
|
||||
switch (true) {
|
||||
case perc >= -50: setSignal(5); break;
|
||||
case perc >= -60: setSignal(4); break;
|
||||
case perc >= -70: setSignal(3); break;
|
||||
case perc >= -80: setSignal(2); break;
|
||||
default: setSignal(1); break;
|
||||
}
|
||||
}, [network.signal])
|
||||
return (
|
||||
<Modal>
|
||||
<CloseBtn className={'close-btn'} onClick={onClose}>
|
||||
|
|
@ -99,11 +173,15 @@ const ModalWifiScaner = ({ network,onClose }: { network: WifiNetworkScanner, onC
|
|||
</CloseBtn>
|
||||
<ModalTitle>
|
||||
<h4>{network.ssid}</h4>
|
||||
<SignalBarsWrapper>
|
||||
<SignalBar active={network.signal >= -120} />
|
||||
<SignalBar active={network.signal >= -70} />
|
||||
<SignalBar active={network.signal >= -50} />
|
||||
</SignalBarsWrapper>
|
||||
<div className={'functionalIcons'}>
|
||||
|
||||
<span onClick={openModalNote} style={{cursor: "pointer"}}>
|
||||
<IconComponent name={buttonNames[16]} width="30" height="30" />
|
||||
</span>
|
||||
<Status>
|
||||
<SignalSVG signal={signal} size={'36px'} color={theme.accent} />
|
||||
</Status>
|
||||
</div>
|
||||
</ModalTitle>
|
||||
<ModalContent>
|
||||
<ModalRow>
|
||||
|
|
@ -134,6 +212,11 @@ const ModalWifiScaner = ({ network,onClose }: { network: WifiNetworkScanner, onC
|
|||
<h6>Скрытая сеть:</h6>
|
||||
<p>{network.hidden ? 'Да' : 'Нет'}</p>
|
||||
</ModalRow>
|
||||
<ModalRow>
|
||||
<h6>Заметка:</h6>
|
||||
<p>{currentNetwork.note ? currentNetwork.note : '-'}</p>
|
||||
</ModalRow>
|
||||
<ModalConnect onClick={openModalNetwork}>{isConnected ? 'Отключиться' : 'Подключиться'}</ModalConnect>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ export interface WifiNetworkScanner {
|
|||
frequency: string;
|
||||
vendor: string;
|
||||
hidden: boolean;
|
||||
note: string;
|
||||
}
|
||||
|
||||
//Точка вайфайл
|
||||
//Точка вайфай
|
||||
const Dot = styled.div<{ top: string; left: string }>`
|
||||
position: absolute;
|
||||
top: ${props => props.top};
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ export const NetworkInterfaces = ({ startConnection, ws }: Props) => {
|
|||
setHasInited(false)
|
||||
initializationAttempt.current = 0;
|
||||
|
||||
const newSocket = new WebSocket(`ws://${ws}:8001/api/v1`);
|
||||
const newSocket = new WebSocket(`wss://${ws}:8001/api/v1`);
|
||||
|
||||
let connectionTimeout;
|
||||
setSocket(newSocket);
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ export const DevicesBar = () => {
|
|||
|
||||
const checkWebSocketAvailability = async (ip: string): Promise<boolean> => {
|
||||
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(() => {
|
||||
testSocket.close();
|
||||
resolve(false);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import noAdmin from '@iconify/icons-ic/baseline-remove-moderator'
|
|||
import refresh from '@iconify/icons-ic/baseline-refresh';
|
||||
import close from '@iconify/icons-ic/round-close';
|
||||
import wifiFind from '@iconify/icons-ic/baseline-wifi-find';
|
||||
import noteEdit from '@iconify/icons-ph/note-pencil';
|
||||
|
||||
export const ICONS = {
|
||||
[buttonNames[1]]: exitToApp,
|
||||
|
|
@ -35,6 +36,7 @@ export const ICONS = {
|
|||
[buttonNames[13]]: noAdmin,
|
||||
[buttonNames[14]]: userSearch,
|
||||
[buttonNames[15]]: wifiFind,
|
||||
[buttonNames[16]]: noteEdit,
|
||||
} as const;
|
||||
|
||||
type IconName = keyof typeof ICONS;
|
||||
|
|
|
|||
|
|
@ -16,4 +16,5 @@ export const buttonNames: names ={
|
|||
13: 'noAdmin',
|
||||
14: 'userSearch',
|
||||
15: 'wifiFind',
|
||||
16: 'noteEdit'
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ interface IpAddressState {
|
|||
export const useIpStore = create<IpAddressState>()(
|
||||
persist(
|
||||
(set)=>({
|
||||
ipAddress: '192:168.1.152',
|
||||
ipAddress: '192:168.1.147',
|
||||
setIpAddress: (newIp: string) => set({ ipAddress: newIp }),
|
||||
}),
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export interface WifiNetworkScanner {
|
|||
frequency: string;
|
||||
vendor: string;
|
||||
hidden: boolean;
|
||||
note: string;
|
||||
}
|
||||
|
||||
interface NetworkStore {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue