Refactoring Dashboard.js => hooks & state
This commit is contained in:
parent
e698c75309
commit
1116ccfb36
30
src/frontend/src/pages/ContextMenu/CtxMenu.js
Normal file
30
src/frontend/src/pages/ContextMenu/CtxMenu.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const CtxMenu = ({contextMenu, handleContextMenuClick }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{contextMenu.visible && (
|
||||||
|
<ul
|
||||||
|
style={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: `${contextMenu.y}px`,
|
||||||
|
left: `${contextMenu.x}px`,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
listStyle: 'none',
|
||||||
|
padding: '2px',
|
||||||
|
boxShadow: '0px 0px 5px rgba(0,0,0,0.3)',
|
||||||
|
zIndex: 1000,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className='context'>
|
||||||
|
<div class="dot"></div>
|
||||||
|
<li className={"btn"} onClick={() => handleContextMenuClick('add')}>Добавить объект</li>
|
||||||
|
<li className={"btn"} onClick={() => handleContextMenuClick('add_base')}>Добавить базовую станцию</li>
|
||||||
|
<li className={"btn"} onClick={() => handleContextMenuClick('save')}>Сохранить промежуточный результат</li>
|
||||||
|
<li className={"btn"} onClick={() => handleContextMenuClick('cancel')}>Отмена</li>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -4,18 +4,23 @@ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
|
|||||||
import Drone from './model/Drone';
|
import Drone from './model/Drone';
|
||||||
import BaseStation from './model/BaseStation';
|
import BaseStation from './model/BaseStation';
|
||||||
import HeightPoint from './model/HeightPoint';
|
import HeightPoint from './model/HeightPoint';
|
||||||
import { RandomHeightPoint } from './helpers/generateRandomHeightPoints'
|
|
||||||
import ModalWindow from './components/Modal/Modal';
|
|
||||||
import { getCustomCookie } from '../Services/Local';
|
import { getCustomCookie } from '../Services/Local';
|
||||||
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal, RunSimulatorSignal } from '../Services/WebsocketHook';
|
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal, RunSimulatorSignal } from '../Services/WebsocketHook';
|
||||||
import './Dashboard.css';
|
import './Dashboard.css';
|
||||||
|
import { ModalDelete } from './Modal/MDelete';
|
||||||
|
import { ModalAdd } from './Modal/MAdd';
|
||||||
|
import { ModalSearch } from './Modal/MSearch';
|
||||||
|
import { ModalJson } from './Modal/MJson';
|
||||||
|
import { ModalMap } from './Modal/MMap';
|
||||||
|
import { CtxMenu } from './ContextMenu/CtxMenu';
|
||||||
|
import { ProgramInterface } from './MainScreen/ProgramInterface';
|
||||||
|
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const mountRef = useRef(null); // Указатель монтирования
|
const mountRef = useRef(null); // Указатель монтирования
|
||||||
const sceneRef = useRef(null); // Указатель на сцену
|
const sceneRef = useRef(null); // Указатель на сцену
|
||||||
const {websocketStruct, sendMessage} = useWebsocketConnection(getCustomCookie("userToken"), 1);
|
const {websocketStruct, sendMessage} = useWebsocketConnection(getCustomCookie("userToken"), 1);
|
||||||
const [heightData, setHeightData] = useState(RandomHeightPoint()); // Высоты
|
const [heightData, setHeightData] = useState([new HeightPoint()]); // Высоты
|
||||||
const [formData, setFormData] = useState({ x: '', y: '', height: '' }); // Форма для ввода данных карты
|
const [formData, setFormData] = useState({ x: '', y: '', height: '' }); // Форма для ввода данных карты
|
||||||
const [mouseState, setMouseState] = useState({ x: 0, y: 0, z: 0 }); // Форма для ввода данных карты
|
const [mouseState, setMouseState] = useState({ x: 0, y: 0, z: 0 }); // Форма для ввода данных карты
|
||||||
const [drones, setDrones] = useState([]) // Все дроны
|
const [drones, setDrones] = useState([]) // Все дроны
|
||||||
@ -66,7 +71,8 @@ const Dashboard = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
setSelectedDrone(foundDrone);
|
setSelectedDrone(foundDrone);
|
||||||
} else if (foundBaseStation) {
|
}
|
||||||
|
if (foundBaseStation) {
|
||||||
// Выделяем найденную базу
|
// Выделяем найденную базу
|
||||||
if (selectedBaseStation) {
|
if (selectedBaseStation) {
|
||||||
selectedBaseStation.getObject().traverse((child) => {
|
selectedBaseStation.getObject().traverse((child) => {
|
||||||
@ -378,7 +384,6 @@ const containsObjectRecursively = (parent, target) => {
|
|||||||
sceneRef.current.add(base.getObject());
|
sceneRef.current.add(base.getObject());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Обработчик ввода на форму высот
|
// Обработчик ввода на форму высот
|
||||||
const handleInputChange = (event) => {
|
const handleInputChange = (event) => {
|
||||||
const { name, value } = event.target;
|
const { name, value } = event.target;
|
||||||
@ -387,7 +392,6 @@ const containsObjectRecursively = (parent, target) => {
|
|||||||
[name]: value,
|
[name]: value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Обработчик ввода на форму объектов
|
// Обработчик ввода на форму объектов
|
||||||
const handleAddInputChange = (event) => {
|
const handleAddInputChange = (event) => {
|
||||||
const { name, value } = event.target;
|
const { name, value } = event.target;
|
||||||
@ -396,8 +400,6 @@ const containsObjectRecursively = (parent, target) => {
|
|||||||
[name]: value,
|
[name]: value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Добавление элемента карты высот (высоты)
|
// Добавление элемента карты высот (высоты)
|
||||||
const handleAddHeight = (event) => {
|
const handleAddHeight = (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -406,7 +408,6 @@ const containsObjectRecursively = (parent, target) => {
|
|||||||
setHeightData((prevData) => [...prevData, newPoint]);
|
setHeightData((prevData) => [...prevData, newPoint]);
|
||||||
setFormData({ x: '', y: '', height: '' });
|
setFormData({ x: '', y: '', height: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
// Изменение настроек
|
// Изменение настроек
|
||||||
const handleSettingsChange = (event) => {
|
const handleSettingsChange = (event) => {
|
||||||
const { name, value } = event.target;
|
const { name, value } = event.target;
|
||||||
@ -415,7 +416,6 @@ const containsObjectRecursively = (parent, target) => {
|
|||||||
[name]: value,
|
[name]: value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Открытие контекстного меню
|
// Открытие контекстного меню
|
||||||
const handleContextMenuClick = (action) => {
|
const handleContextMenuClick = (action) => {
|
||||||
if (action === 'add_base'){
|
if (action === 'add_base'){
|
||||||
@ -429,413 +429,62 @@ const containsObjectRecursively = (parent, target) => {
|
|||||||
setContextMenu({ ...contextMenu, visible: false });
|
setContextMenu({ ...contextMenu, visible: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
// IS LOADING
|
|
||||||
// <div class="spinner-border text-primary" role="status">
|
|
||||||
// <span class="visually-hidden">Loading...</span>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<div className='col'>
|
<div className='col'>
|
||||||
{/* TODO: USERS BADGE */}
|
|
||||||
<h4><b>Drone</b> Network Simulator - окно разработки</h4>
|
<h4><b>Drone</b> Network Simulator - окно разработки</h4>
|
||||||
</div>
|
</div>
|
||||||
|
<ModalAdd
|
||||||
|
modals={modals.isModalAddOpen}
|
||||||
|
closeAllModals={closeAllModals}
|
||||||
|
handleAddInputChange={handleAddInputChange}
|
||||||
|
handleTypeChange={handleTypeChange}
|
||||||
|
objectType={objectType}
|
||||||
|
formObjectData={formObjectData}
|
||||||
|
modalAddDroneOrBaseStation={modalAddDroneOrBaseStation}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
<ModalWindow isOpen={modals.isModalAddOpen} onClose={closeAllModals}>
|
<ModalSearch
|
||||||
<div className="modal d-block" tabIndex="-1">
|
isModalSearchOpen={modals.isModalSearchOpen}
|
||||||
<div className="modal-dialog">
|
closeAllModals={closeAllModals}
|
||||||
<div className="modal-content">
|
handleSearch={handleSearch}
|
||||||
<div className="modal-header">
|
searchTerm={searchTerm}
|
||||||
<h5 className="modal-title">Добавление объекта</h5>
|
setSearchTerm={setSearchTerm}
|
||||||
<button type="button" className="btn-close" onClick={closeAllModals}></button>
|
|
||||||
</div>
|
|
||||||
<div className="modal-body">
|
|
||||||
<div className="mb-3">
|
|
||||||
<label>Тип объекта:</label>
|
|
||||||
<div>
|
|
||||||
<div className="form-check form-check-inline">
|
|
||||||
<input
|
|
||||||
className="form-check-input"
|
|
||||||
type="radio"
|
|
||||||
name="objectType"
|
|
||||||
id="drone"
|
|
||||||
checked={objectType === 1}
|
|
||||||
onChange={() => handleTypeChange(1)}
|
|
||||||
/>
|
/>
|
||||||
<label className="form-check-label" htmlFor="drone">Дрон</label>
|
|
||||||
</div>
|
|
||||||
<div className="form-check form-check-inline">
|
|
||||||
<input
|
|
||||||
className="form-check-input"
|
|
||||||
type="radio"
|
|
||||||
name="objectType"
|
|
||||||
id="baseStation"
|
|
||||||
checked={objectType === 2}
|
|
||||||
onChange={() => handleTypeChange(2)}
|
|
||||||
/>
|
|
||||||
<label className="form-check-label" htmlFor="baseStation">Базовая станция</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-3">
|
<ModalDelete
|
||||||
<label>Название объекта:</label>
|
isModalDeleteOpen={modals.isModalDeleteOpen}
|
||||||
<input
|
closeAllModals={closeAllModals}
|
||||||
type="text"
|
handleDeleteSignal={handleDeleteSignal}
|
||||||
className="form-control"
|
|
||||||
placeholder="Введите название"
|
|
||||||
name='name'
|
|
||||||
value={formObjectData.name}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mb-3">
|
<ModalJson
|
||||||
<label>Координаты:</label>
|
isModalOpen={modals.isModalOpen}
|
||||||
<div className="input-group mb-2">
|
closeAllModals={closeAllModals}
|
||||||
<span className="input-group-text">X</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
value={formObjectData.coordinates_x}
|
|
||||||
name='coordinates_x'
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Y</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
name='coordinates_y'
|
|
||||||
value={formObjectData.coordinates_y}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Z</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
name='coordinates_z'
|
|
||||||
value={formObjectData.coordinates_z}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<label>Параметры антенны:</label>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Радиус антенны</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
value={formObjectData.antennaRadius}
|
|
||||||
name='antennaRadius'
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Направление X</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
value={formObjectData.antennaDirection_x}
|
|
||||||
name='antennaDirection_x'
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Направление Y</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
name='antennaDirection_y'
|
|
||||||
value={formObjectData.antennaDirection_y}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Направление Z</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
name='antennaDirection_z'
|
|
||||||
value={formObjectData.antennaDirection_z}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Модуляция</span>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
name='modulation'
|
|
||||||
value={formObjectData.modulation}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Пропускная способность</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
name='bandwidth'
|
|
||||||
value={formObjectData.bandwidth}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="input-group mb-2">
|
|
||||||
<span className="input-group-text">Скорость</span>
|
|
||||||
<input
|
|
||||||
type="number"
|
|
||||||
className="form-control"
|
|
||||||
name='dataRate'
|
|
||||||
value={formObjectData.dataRate}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
<ModalMap isModalMapOpen={modals.isModalMapOpen}
|
||||||
|
closeAllModals={closeAllModals}
|
||||||
{objectType === 1 && (
|
handleAddHeight={handleAddHeight}
|
||||||
<>
|
formData={formData}
|
||||||
<div className="mb-3">
|
handleInputChange={handleInputChange}
|
||||||
<label>Скорость перемещения:</label>
|
mapSettings={mapSettings}
|
||||||
<input
|
handleSettingsChange={handleSettingsChange}/>
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
name='speed'
|
|
||||||
value={formObjectData.speed}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<label>Название Mesh сети:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
name='meshName'
|
|
||||||
value={formObjectData.meshName}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3">
|
|
||||||
<label>Точки перемещения:</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className="form-control"
|
|
||||||
name='wayPoints'
|
|
||||||
value={formObjectData.wayPoints}
|
|
||||||
onChange={handleAddInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div className="modal-footer">
|
|
||||||
<button type="button" className="btn btn-secondary" onClick={closeAllModals}>Закрыть</button>
|
|
||||||
<button type="button" className="btn btn-primary" onClick={() => { modalAddDroneOrBaseStation(); }}>Добавить</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ModalWindow>
|
|
||||||
|
|
||||||
<ModalWindow isOpen={modals.isModalSearchOpen} onClose={closeAllModals}>
|
|
||||||
<h2>Поиск</h2>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Введите имя"
|
|
||||||
value={searchTerm}
|
|
||||||
onChange={(e) => setSearchTerm(e.target.value)}
|
|
||||||
/>
|
|
||||||
<button onClick={handleSearch}>Найти</button>
|
|
||||||
</ModalWindow>
|
|
||||||
|
|
||||||
<ModalWindow isOpen={modals.isModalDeleteOpen} onClose={closeAllModals}>
|
|
||||||
<h2>Удаление</h2>
|
|
||||||
<h2>Вы точно хотите удалить объект X?</h2>
|
|
||||||
<button onClick={closeAllModals}>Отмена</button>
|
|
||||||
<button onClick={() => handleDeleteSignal(1) }>Удалить</button>
|
|
||||||
</ModalWindow>
|
|
||||||
|
|
||||||
<ModalWindow isOpen={modals.isModalOpen} onClose={closeAllModals}>
|
|
||||||
<h2>Загрузка JSON</h2>
|
|
||||||
<p>Выберите или переташите файл для загрузки</p>
|
|
||||||
<input type='file'/>
|
|
||||||
<button onClick={closeAllModals}>Отмена</button>
|
|
||||||
<button onClick={() => alert('Загружено')}>Загрузить</button>
|
|
||||||
</ModalWindow>
|
|
||||||
|
|
||||||
{/* Форма для добавления новых высот */}
|
|
||||||
<ModalWindow isOpen={modals.isModalMapOpen} onClose={closeAllModals}>
|
|
||||||
<h2>Настройки карты</h2>
|
|
||||||
<div className="columns">
|
|
||||||
<div className='column'>
|
|
||||||
<form onSubmit={handleAddHeight} style={{ marginTop: '20px' }}>
|
|
||||||
<div>
|
|
||||||
<label>Координата X:</label>
|
|
||||||
<input
|
|
||||||
className="input is-primary"
|
|
||||||
type="number"
|
|
||||||
name="x"
|
|
||||||
value={formData.x}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Координата Y:</label>
|
|
||||||
<input
|
|
||||||
className="input is-primary"
|
|
||||||
type="number"
|
|
||||||
name="y"
|
|
||||||
value={formData.y}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label>Высота:</label>
|
|
||||||
<input
|
|
||||||
className="input is-primary"
|
|
||||||
type="number"
|
|
||||||
name="height"
|
|
||||||
value={formData.height}
|
|
||||||
onChange={handleInputChange}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<button className='button' type="submit">Добавить точку высоты</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
{/* Настройки карты */}
|
|
||||||
<div className='column'>
|
|
||||||
<div style={{ marginTop: '20px' }}>
|
|
||||||
<h2>Настройки карты</h2>
|
|
||||||
<div>
|
|
||||||
<label>Максимальная высота:</label>
|
|
||||||
<input
|
|
||||||
className="input"
|
|
||||||
type="number"
|
|
||||||
name="maxHeight"
|
|
||||||
value={mapSettings.maxHeight}
|
|
||||||
onChange={handleSettingsChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button onClick={closeAllModals}>Отмена</button>
|
|
||||||
<button onClick={() => alert('Обновлена карта!')}>Готово</button>
|
|
||||||
</ModalWindow>
|
|
||||||
|
|
||||||
{/* Окно программы */}
|
{/* Окно программы */}
|
||||||
<div className='coler-border'>
|
<ProgramInterface
|
||||||
<div>
|
mouseState={mouseState}
|
||||||
<p> X: {mouseState.x} Y: {mouseState.y} Z: {mouseState.z}</p>
|
mountRef={mountRef}
|
||||||
</div>
|
openModal={openModal}
|
||||||
<div ref={mountRef} style={{
|
sendMessage={sendMessage}
|
||||||
minWidth: '100%',
|
RunSimulatorSignal={RunSimulatorSignal}
|
||||||
minHeight: '60vh',
|
getCustomCookie={getCustomCookie}
|
||||||
position: 'relative'
|
/>
|
||||||
}} />
|
<CtxMenu
|
||||||
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
|
contextMenu={contextMenu}
|
||||||
<div class="btn-group me-2" role="group" aria-label="First group">
|
handleContextMenuClick={handleContextMenuClick}
|
||||||
|
/>
|
||||||
<button type="button" onClick={() => openModal('isModalAddOpen')} class="btn btn-success">
|
|
||||||
<i class="bi-plus"/>Добавить
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" onClick={() => openModal('isModalDeleteOpen')} class="btn btn-success">
|
|
||||||
<i class="bi-trash"/>Удалить
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" onClick={() => openModal('isModalSearchOpen')} class="btn btn-success">
|
|
||||||
<i class="bi-search"/>Выбрать
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-success">
|
|
||||||
<i class="bi-save"/>Сохранить
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="btn-group me-2" role="group" aria-label="Second group">
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-secondary">
|
|
||||||
<i class="bi-box-arrow-in-down"/>Загрузить данные
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-secondary">
|
|
||||||
<i class="bi-filetype-json"/>Выгрузить
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" onClick={() => openModal('isModalMapOpen')} class="btn btn-secondary">
|
|
||||||
<i class="bi-map"/>Настройки карты
|
|
||||||
</button>
|
|
||||||
|
|
||||||
{/* <button type="button" class="btn btn-secondary">6</button> */}
|
|
||||||
</div>
|
|
||||||
<div class="btn-group me-2" role="group" aria-label="Third group">
|
|
||||||
<button type="button" class="btn btn-info">
|
|
||||||
<i class="bi-play" onClick={() => {
|
|
||||||
sendMessage(RunSimulatorSignal(getCustomCookie("userToken")))
|
|
||||||
|
|
||||||
}}/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btn-group me-2" role="group" aria-label="Последние 3 симуляции">
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-info">
|
|
||||||
<i class="bi-play"/> Симуляция : 01:00:04
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-info">
|
|
||||||
<i class="bi-play"/> Симуляция : 03:00:04
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-info">
|
|
||||||
<i class="bi-play"/> Симуляция : 03:00:04
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h1>Websocket data</h1>
|
|
||||||
{websocketStruct ? (
|
|
||||||
<pre>{JSON.stringify(websocketStruct, null, 2)}</pre>
|
|
||||||
) : (
|
|
||||||
<p>Waiting for WebSocket data...</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{/* Контекстное меню */}
|
|
||||||
{contextMenu.visible && (
|
|
||||||
<ul
|
|
||||||
style={{
|
|
||||||
position: 'absolute',
|
|
||||||
top: `${contextMenu.y}px`,
|
|
||||||
left: `${contextMenu.x}px`,
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
listStyle: 'none',
|
|
||||||
padding: '2px',
|
|
||||||
boxShadow: '0px 0px 5px rgba(0,0,0,0.3)',
|
|
||||||
zIndex: 1000,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className='context'>
|
|
||||||
<div class="dot"></div>
|
|
||||||
<li className={"btn"} onClick={() => handleContextMenuClick('add')}>Добавить объект</li>
|
|
||||||
<li className={"btn"} onClick={() => handleContextMenuClick('add_base')}>Добавить базовую станцию</li>
|
|
||||||
<li className={"btn"} onClick={() => handleContextMenuClick('save')}>Сохранить промежуточный результат</li>
|
|
||||||
<li className={"btn"} onClick={() => handleContextMenuClick('cancel')}>Отмена</li>
|
|
||||||
</div>
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
78
src/frontend/src/pages/MainScreen/ProgramInterface.js
Normal file
78
src/frontend/src/pages/MainScreen/ProgramInterface.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const ProgramInterface = ({mouseState, mountRef, openModal, sendMessage, RunSimulatorSignal, getCustomCookie}) => {
|
||||||
|
return (
|
||||||
|
<div className='coler-border'>
|
||||||
|
<div>
|
||||||
|
<p> X: {mouseState.x} Y: {mouseState.y} Z: {mouseState.z}</p>
|
||||||
|
</div>
|
||||||
|
<div ref={mountRef} style={{
|
||||||
|
minWidth: '100%',
|
||||||
|
minHeight: '60vh',
|
||||||
|
position: 'relative'
|
||||||
|
}} />
|
||||||
|
<div class="btn-toolbar" role="toolbar" aria-label="Toolbar with button groups">
|
||||||
|
<div class="btn-group me-2" role="group" aria-label="First group">
|
||||||
|
|
||||||
|
<button type="button" onClick={() => openModal('isModalAddOpen')} class="btn btn-success">
|
||||||
|
<i class="bi-plus"/>Добавить
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" onClick={() => openModal('isModalDeleteOpen')} class="btn btn-success">
|
||||||
|
<i class="bi-trash"/>Удалить
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" onClick={() => openModal('isModalSearchOpen')} class="btn btn-success">
|
||||||
|
<i class="bi-search"/>Выбрать
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-success">
|
||||||
|
<i class="bi-save"/>Сохранить
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="btn-group me-2" role="group" aria-label="Second group">
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-secondary">
|
||||||
|
<i class="bi-box-arrow-in-down"/>Загрузить данные
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-secondary">
|
||||||
|
<i class="bi-filetype-json"/>Выгрузить
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" onClick={() => openModal('isModalMapOpen')} class="btn btn-secondary">
|
||||||
|
<i class="bi-map"/>Настройки карты
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* <button type="button" class="btn btn-secondary">6</button> */}
|
||||||
|
</div>
|
||||||
|
<div class="btn-group me-2" role="group" aria-label="Third group">
|
||||||
|
<button type="button" class="btn btn-info">
|
||||||
|
<i class="bi-play" onClick={() => {
|
||||||
|
sendMessage(RunSimulatorSignal(getCustomCookie("userToken")))
|
||||||
|
|
||||||
|
}}/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group me-2" role="group" aria-label="Последние 3 симуляции">
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-info">
|
||||||
|
<i class="bi-play"/> Симуляция : 01:00:04
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-info">
|
||||||
|
<i class="bi-play"/> Симуляция : 03:00:04
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-info">
|
||||||
|
<i class="bi-play"/> Симуляция : 03:00:04
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
209
src/frontend/src/pages/Modal/MAdd.js
Normal file
209
src/frontend/src/pages/Modal/MAdd.js
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ModalWindow from '../components/Modal/Modal';
|
||||||
|
|
||||||
|
|
||||||
|
export const ModalAdd = ({isModalAddOpen, objectType, formObjectData, modalAddDroneOrBaseStation, closeAllModals, handleAddInputChange, handleTypeChange}) => {
|
||||||
|
return (
|
||||||
|
<ModalWindow isOpen={isModalAddOpen} onClose={closeAllModals}>
|
||||||
|
<div className="modal d-block" tabIndex="-1">
|
||||||
|
<div className="modal-dialog">
|
||||||
|
<div className="modal-content">
|
||||||
|
<div className="modal-header">
|
||||||
|
<h5 className="modal-title">Добавление объекта</h5>
|
||||||
|
<button type="button" className="btn-close" onClick={closeAllModals}></button>
|
||||||
|
</div>
|
||||||
|
<div className="modal-body">
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Тип объекта:</label>
|
||||||
|
<div>
|
||||||
|
<div className="form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="objectType"
|
||||||
|
id="drone"
|
||||||
|
checked={objectType === 1}
|
||||||
|
onChange={() => handleTypeChange(1)}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="drone">Дрон</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-check form-check-inline">
|
||||||
|
<input
|
||||||
|
className="form-check-input"
|
||||||
|
type="radio"
|
||||||
|
name="objectType"
|
||||||
|
id="baseStation"
|
||||||
|
checked={objectType === 2}
|
||||||
|
onChange={() => handleTypeChange(2)}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="baseStation">Базовая станция</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Название объекта:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
placeholder="Введите название"
|
||||||
|
name='name'
|
||||||
|
value={formObjectData.name}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Координаты:</label>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">X</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
value={formObjectData.coordinates_x}
|
||||||
|
name='coordinates_x'
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Y</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
name='coordinates_y'
|
||||||
|
value={formObjectData.coordinates_y}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Z</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
name='coordinates_z'
|
||||||
|
value={formObjectData.coordinates_z}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Параметры антенны:</label>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Радиус антенны</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
value={formObjectData.antennaRadius}
|
||||||
|
name='antennaRadius'
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Направление X</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
value={formObjectData.antennaDirection_x}
|
||||||
|
name='antennaDirection_x'
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Направление Y</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
name='antennaDirection_y'
|
||||||
|
value={formObjectData.antennaDirection_y}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Направление Z</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
name='antennaDirection_z'
|
||||||
|
value={formObjectData.antennaDirection_z}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Модуляция</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
name='modulation'
|
||||||
|
value={formObjectData.modulation}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Пропускная способность</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
name='bandwidth'
|
||||||
|
value={formObjectData.bandwidth}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="input-group mb-2">
|
||||||
|
<span className="input-group-text">Скорость</span>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="form-control"
|
||||||
|
name='dataRate'
|
||||||
|
value={formObjectData.dataRate}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{objectType === 1 && (
|
||||||
|
<>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Скорость перемещения:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
name='speed'
|
||||||
|
value={formObjectData.speed}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Название Mesh сети:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
name='meshName'
|
||||||
|
value={formObjectData.meshName}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3">
|
||||||
|
<label>Точки перемещения:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control"
|
||||||
|
name='wayPoints'
|
||||||
|
value={formObjectData.wayPoints}
|
||||||
|
onChange={handleAddInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="modal-footer">
|
||||||
|
<button type="button" className="btn btn-secondary" onClick={closeAllModals}>Закрыть</button>
|
||||||
|
<button type="button" className="btn btn-primary" onClick={() => { modalAddDroneOrBaseStation(); }}>Добавить</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalWindow>
|
||||||
|
)
|
||||||
|
}
|
14
src/frontend/src/pages/Modal/MDelete.js
Normal file
14
src/frontend/src/pages/Modal/MDelete.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ModalWindow from '../components/Modal/Modal';
|
||||||
|
|
||||||
|
|
||||||
|
export const ModalDelete = ({isModalDeleteOpen, closeAllModals, handleDeleteSignal}) => {
|
||||||
|
return (
|
||||||
|
<ModalWindow isOpen={isModalDeleteOpen} onClose={closeAllModals}>
|
||||||
|
<h2>Удаление</h2>
|
||||||
|
<h2>Вы точно хотите удалить объект X?</h2>
|
||||||
|
<button onClick={closeAllModals}>Отмена</button>
|
||||||
|
<button onClick={() => handleDeleteSignal(1) }>Удалить</button>
|
||||||
|
</ModalWindow>
|
||||||
|
)
|
||||||
|
}
|
15
src/frontend/src/pages/Modal/MJson.js
Normal file
15
src/frontend/src/pages/Modal/MJson.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ModalWindow from '../components/Modal/Modal';
|
||||||
|
|
||||||
|
|
||||||
|
export const ModalJson= ({isModalOpen, closeAllModals}) => {
|
||||||
|
return (
|
||||||
|
<ModalWindow isOpen={isModalOpen} onClose={closeAllModals}>
|
||||||
|
<h2>Загрузка JSON</h2>
|
||||||
|
<p>Выберите или переташите файл для загрузки</p>
|
||||||
|
<input type='file'/>
|
||||||
|
<button onClick={closeAllModals}>Отмена</button>
|
||||||
|
<button onClick={() => alert('Загружено')}>Загрузить</button>
|
||||||
|
</ModalWindow>
|
||||||
|
)
|
||||||
|
}
|
69
src/frontend/src/pages/Modal/MMap.js
Normal file
69
src/frontend/src/pages/Modal/MMap.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ModalWindow from '../components/Modal/Modal';
|
||||||
|
|
||||||
|
|
||||||
|
export const ModalMap = ({isModalMapOpen, closeAllModals, handleAddHeight, formData, handleInputChange, mapSettings, handleSettingsChange}) => {
|
||||||
|
return (
|
||||||
|
<ModalWindow isOpen={isModalMapOpen} onClose={closeAllModals}>
|
||||||
|
<h2>Настройки карты</h2>
|
||||||
|
<div className="columns">
|
||||||
|
<div className='column'>
|
||||||
|
<form onSubmit={handleAddHeight} style={{ marginTop: '20px' }}>
|
||||||
|
<div>
|
||||||
|
<label>Координата X:</label>
|
||||||
|
<input
|
||||||
|
className="input is-primary"
|
||||||
|
type="number"
|
||||||
|
name="x"
|
||||||
|
value={formData.x}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Координата Y:</label>
|
||||||
|
<input
|
||||||
|
className="input is-primary"
|
||||||
|
type="number"
|
||||||
|
name="y"
|
||||||
|
value={formData.y}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label>Высота:</label>
|
||||||
|
<input
|
||||||
|
className="input is-primary"
|
||||||
|
type="number"
|
||||||
|
name="height"
|
||||||
|
value={formData.height}
|
||||||
|
onChange={handleInputChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button className='button' type="submit">Добавить точку высоты</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{/* Настройки карты */}
|
||||||
|
<div className='column'>
|
||||||
|
<div style={{ marginTop: '20px' }}>
|
||||||
|
<h2>Настройки карты</h2>
|
||||||
|
<div>
|
||||||
|
<label>Максимальная высота:</label>
|
||||||
|
<input
|
||||||
|
className="input"
|
||||||
|
type="number"
|
||||||
|
name="maxHeight"
|
||||||
|
value={mapSettings.maxHeight}
|
||||||
|
onChange={handleSettingsChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button onClick={closeAllModals}>Отмена</button>
|
||||||
|
<button onClick={() => alert('Обновлена карта!')}>Готово</button>
|
||||||
|
</ModalWindow>
|
||||||
|
)
|
||||||
|
}
|
18
src/frontend/src/pages/Modal/MSearch.js
Normal file
18
src/frontend/src/pages/Modal/MSearch.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ModalWindow from '../components/Modal/Modal';
|
||||||
|
|
||||||
|
|
||||||
|
export const ModalSearch = ({isModalSearchOpen, closeAllModals, handleSearch, searchTerm, setSearchTerm}) => {
|
||||||
|
return (
|
||||||
|
<ModalWindow isOpen={isModalSearchOpen} onClose={closeAllModals}>
|
||||||
|
<h2>Поиск</h2>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Введите имя"
|
||||||
|
value={searchTerm}
|
||||||
|
onChange={(e) => setSearchTerm(e.target.value)}
|
||||||
|
/>
|
||||||
|
<button onClick={handleSearch}>Найти</button>
|
||||||
|
</ModalWindow>
|
||||||
|
)
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
import HeightPoint from '../model/HeightPoint';
|
|
||||||
|
|
||||||
export const RandomHeightPoint = () => {
|
|
||||||
let result = [];
|
|
||||||
for (let i = 0; i < 100; i++) {
|
|
||||||
for (let j = 0; j < 100; j++) {
|
|
||||||
result.push(new HeightPoint(i, j, Math.random() * 10 + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user