diff --git a/.woodpecker/.woodpecker.yml b/.woodpecker/.woodpecker.yml index 4b83667..801de92 100644 --- a/.woodpecker/.woodpecker.yml +++ b/.woodpecker/.woodpecker.yml @@ -9,7 +9,7 @@ steps: GONETS: from_secret: GONETS commands: - - bash + - echo $SHELL # ПОДГОТОВКА ГИТА И КЛОНИРОВАНИЕ GONETS - apt update - apt install -y git git-lfs @@ -18,19 +18,29 @@ steps: # УСТАНОВКА НЕОБХОДИМЫХ ЗАВИСИМОСТЕЙ НА СИСТЕМЕ - apt update - - apt install -y python3 python3-pip python3-poetry nodejs npm debhelper devscripts build-essential fakeroot dh-make dpkg-dev + - apt install -y python3 python3.11-venv python3-pip python3-poetry nodejs npm debhelper devscripts build-essential fakeroot dh-make dpkg-dev cmake libgirepository1.0-dev gobject-introspection libcairo2-dev pkg-config python3-dev libdbus-1-dev - python3 --version - node -v - npm -v # ПОДГОТОВКА СПИСКА PYTHON ЗАВИСИМОСТЕЙ GONETS - - curl -sSL https://install.python-poetry.org | python3 - - - export PATH="/root/.local/bin:$PATH" + - rm -rf /usr/lib/python3.11/EXTERNALLY-MANAGED + - rm -rf /root/.local/share/pypoetry + - rm -rf /root/.poetry + - rm -rf /usr/bin/poetry + - pip install pipx + - pipx ensurepath + - pipx install poetry + - echo 'export PATH="$HOME/.local/bin:$PATH"' >> /root/.bashrc + - . /root/.bashrc - poetry --version - cd gonets/SRV + - poetry env activate + - poetry add poetry-plugin-export - poetry install + - poetry self update - rm -f requirements.txt - - poetry export -f requirements.txt --output requirements.txt --without-hashes + - poetry run poetry export -f requirements.txt --output requirements.txt --without-hashes # ПОДГОТОВКА И СБОРКА FRONTEND ЧАСТИ GONETS - cd gonets/FRONT/DEV diff --git a/FRONT/BUILD/index.html b/FRONT/BUILD/index.html new file mode 100644 index 0000000..8f4d4d1 --- /dev/null +++ b/FRONT/BUILD/index.html @@ -0,0 +1,13 @@ + +
+ + +
- v 0.0.3
+
+ ГоNets — минимально работоспособный кроссплатформенный продукт (MVP) для демонстрации нашего подхода к управлению настройками ПК в корпоративной среде.
-Возможности:
-Приложение ГоNets является минимально работоспособным кроссплатформенным продуктом (MVP) для демонстрации нашего подхода к управлению настройками ПК в корпоративной среде.
+Программное обеспечение исключительно для ознакомления и домашнего использования.
- Перейти на ГоNets-PRO -Данное приложение умеет:
+- Отображать в графическом виде активные сетевые ресурсы
+- Настраивать сетевые параметры локального и удаленных сетевых ресурсов
+- Отображать и изменять взаимодействие сетевых ресурсов с установленным Клиентом ГоNets
+Программное обеспечение исключительно для ознакомления и домашнего использования.
+Для коммерческого использования приобретите версию ГоNets-PRO (Подробная информация на странице продукта)
+Ссылка на домашнюю страницу:
+ https://gossys.dev/pages/projects/gonets +Инструкции и информация:
+ https://wiki.gossys.dev/ru/gonets +Распространяется под лицензией GosysPUB текущей версии.
+Полный текст актуальной лицензии:
+ https://wiki.gossys.dev/ru/lic/GosysPUB +Разработано и поддерживается ООО «Гибридные Офисные Системы» 2024-2025 г. Все права защищены.
+Узлы не найдены
+Устройства не найдены
) : null} > ); diff --git a/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx b/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx index 77e064c..ebe71a9 100644 --- a/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx +++ b/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx @@ -30,13 +30,13 @@ const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps return ( <>Узлы не найдены
+Устройства не найдены
) : null} > ); diff --git a/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx b/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx index 19ca497..cb816ca 100644 --- a/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx +++ b/FRONT/BUILD/resources/app/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx @@ -77,7 +77,7 @@ const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>` span { position: absolute; display: inline-block; - background: ${(props) => props.theme.scannerColor}; + background: ${(props) => props.theme.accent}; top: 50%; left: 50%; transform: translate(-50%, -50%); @@ -163,7 +163,7 @@ export default function UserScanner() { return (+ MAC: {device.mac} +
+ +{value?.label || 'Select an option'}
+Версия IP:
+v{data.ipData.ipVersion}
+Метод:
+{typeMap[data.ipData.ipType]}
+IPv{data.ipData.ipVersion}-Addr:
+ {isInput ? ( + handleChange('newIp', value)} + onBlur={handleBlur} + onFocus={handleFocus} + style={{fontSize: '12px', padding: '4px 10px'}} + /> + ) : ( +{data.ipData.ipAdress}
+ )} + +IPv{data.ipData.ipVersion}-GW:
+ {isInput ? ( + handleChange('newGate', value)} + onBlur={handleBlur} + onFocus={handleFocus} + style={{fontSize: '12px', padding: '4px 10px'}} + /> + ) : ( +{data.ipData.ipGate}
+ )} +IPv{data.ipData.ipVersion}-DNS:
+ {isInput ? ( + handleChange('newDns', value)} + onBlur={handleBlur} + onFocus={handleFocus} + style={{fontSize: '12px', padding: '4px 10px'}} + /> + ) : ( +{data.ipData.ipDns.join(', ')}
+ )} +{data.label}
+ + {/*Конфигурация
+MAC:
+{data.networkData.mac}
+MTU:
+{data.networkData.mtu}
+{data.label}
+ + + {data.port && +{data.port}
+ } ++ {error} +
+Пожалуйста, проверьте доступ к адресу и попробуйте снова.
+Вы собираетесь отключиться от сети "{address}". Все активные подключения будут прерваны.
+Интерфейс: {ipData.device}
+--{'>'}
+{ipData.connection}
+Текущий ip: {ipData.currentIp}
+Текущий шлюз: {ipData.currentGate}
+Текущий DNS: {ipData.currentDns}
+Новый ip: {ipData.newIp}
+Новый шлюз: {ipData.newGate}
+Новый DNS: {ipData.newDns}
++ Неверный пароль оператора +
+ )} + +В данном режиме доступа ограничиваются полномочия администратора.
+Это окно можно закрыть, либо оно пропадёт само
+{ipAddress}
+ } + +Перед началом работы необходимо создать пароль оператора приложения
++ Пароли не совпадают! +
+ )} +
+ v 0.0.3
+ГоNets — минимально работоспособный кроссплатформенный продукт (MVP) для демонстрации нашего подхода к управлению настройками ПК в корпоративной среде.
+Возможности:
+Программное обеспечение исключительно для ознакомления и домашнего использования.
+ Перейти на ГоNets-PRO +Узлы не найдены
+ ) : null} + > + ); +}; + +export default ListUsers; \ No newline at end of file diff --git a/FRONT/DEV/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx b/FRONT/DEV/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx new file mode 100644 index 0000000..77e064c --- /dev/null +++ b/FRONT/DEV/src/components/workSpace/modules/appModules/usersScanner/modules/TableUsers.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import styled from 'styled-components'; +import DeviceCard from "../../../../../UI/Dropdown/DeviceCard"; +import {DeviceUser} from "../../../../../../store/useDeviceStore"; +import TableScanner from "../../../../../UI/tables/TableScanner"; + +const ScanBtn = styled.button` + position: relative; + padding: 14px 22px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 12px; + font-size: 18px; + transition: .4s ease; + &:hover{ + transform: scale(1.03); + } +` + +interface ListUsersProps { + loading: boolean; + handleScan: ()=>void; + devices: DeviceUser[]; + scanInitiated: boolean; +} + +const ListUsers = ({loading, handleScan, devices, scanInitiated}: ListUsersProps) => { + + return ( + <> +Узлы не найдены
+ ) : null} + > + ); +}; + +export default ListUsers; \ No newline at end of file diff --git a/FRONT/DEV/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx b/FRONT/DEV/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx new file mode 100644 index 0000000..19ca497 --- /dev/null +++ b/FRONT/DEV/src/components/workSpace/modules/appModules/usersScanner/userScanner.tsx @@ -0,0 +1,191 @@ +import { useIpStore } from "../../../../../store"; +import styled, { keyframes } from "styled-components"; +import { useState } from "react"; +import { NetworkService } from "../../../../../api/request"; +import ListUsers from "./modules/ListUsers"; +import TableUsers from "./modules/TableUsers"; +import DropdownType from "../../../../UI/Dropdown/DropdownType"; +import useNetworkStore from "../../../../../store/useDeviceStore"; + +type Option ={ + value: number, + label: string, +} + +// Анимации +const ring1 = keyframes` + 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.12; } + 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.2; } + 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.12; } +`; + +const ring2 = keyframes` + 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.08; } + 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.15; } + 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.08; } +`; + +const ring3 = keyframes` + 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.04; } + 50% { transform: translate(-50%, -50%) scale(1.1); opacity: 0.1; } + 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.04; } +`; +const dotAnimation = keyframes` + 0% { content: '.'; } + 33% { content: '..'; } + 66% { content: '...'; } + 100% { content: '.'; } +`; +const pulse = keyframes` + 0% { transform: translate(-50%, -50%) scale(1); } + 50% { transform: translate(-50%, -50%) scale(1.1); } + 100% { transform: translate(-50%, -50%) scale(1); } +`; + +// Стили +const Wrapper = styled.div<{ scanInitiated: boolean, loading: boolean}>` + display: flex; + flex-direction: column; + align-items: center; + justify-content:${({scanInitiated, loading})=>(scanInitiated && !loading ? 'start' : 'center')}; + height: 100%; + width: 100%; + background: ${(props) => props.theme.background}; + padding: 50px; + box-sizing: border-box; + gap: 24px; + transition: justify-content .4s ease; + overflow-y: auto; + overflow-x: hidden; + position: relative; +`; +const TitleWrapper = styled.h2` + position: absolute; + top: 20px; + left: 50%; + transform: translateX(-50%); + font-size: 32px; + width: max-content; +` +const UserLocate = styled.div<{ loading: boolean, scanInitiated: boolean }>` + width: 60px; + height: 60px; + border-radius: 50%; + position: relative; + transition: .4s ease; + transform: ${({scanInitiated,loading})=>(scanInitiated && !loading ? 'scale(0)' : 'scale(1)')}; + span { + position: absolute; + display: inline-block; + background: ${(props) => props.theme.scannerColor}; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + border-radius: 50%; + &.center { + width: 60px; + height: 60px; + animation: ${({ loading }) => (loading ? pulse : "none")} 2s ease infinite; + } + &.ring1 { + opacity: 0.12; + width: 250px; + height: 250px; + animation: ${({ loading }) => (loading ? ring1 : "none")} 4s linear infinite; + } + + &.ring2 { + opacity: 0.08; + width: 400px; + height: 400px; + animation: ${({ loading }) => (loading ? ring2 : "none")} 4s linear infinite; + animation-delay: ${({ loading }) => (loading ? "0.1s" : "0")}; + } + + &.ring3 { + opacity: 0.04; + width: 550px; + height: 550px; + animation: ${({ loading }) => (loading ? ring3 : "none")} 4s linear infinite; + animation-delay: ${({ loading }) => (loading ? "0.2s" : "0")}; + } + } +`; + +const LoadingText = styled.div` + position: relative; + padding: 14px 22px; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 12px; + font-size: 18px; +`; +const ScanningText = styled.span` + &::after { + content: '.'; + animation: ${dotAnimation} 1.5s infinite; + } +`; + + +export default function UserScanner() { + const { ipAddress } = useIpStore(); + const [loading, setLoading] = useState(false); + const { devices, setDevices } = useNetworkStore(); + const [scanInitiated, setScanInitiated] = useState(devices.length > 0); + + // Сканирование + const handleScan = async () => { + try { + setLoading(true); + setScanInitiated(true); + const res = await NetworkService.scanUser(ipAddress); + console.log(res); + setDevices(res.data.devices || []); + } catch (err) { + console.error("Ошибка сканирования сети:", err); + setDevices([]) + } finally { + setLoading(false); + } + }; + + // Способ отображения + const viewOptions: Option[] = [ + { value: 1, label: 'Таблица' }, + { value: 2, label: 'Список' }, + ]; + const [selectedView, setSelectedView] = useState