feat: Implement date formatting utility functions and update components to use formatted timestamps for improved readability and consistency across the application.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m47s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m47s
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { IconPlus } from '@tabler/icons-react';
|
||||
import { SERVER_TYPE_OPTIONS } from '../../utils/serverUtils.js';
|
||||
|
||||
/**
|
||||
* Модальное окно для добавления нового сервера
|
||||
*/
|
||||
function AddServerModal({ show, newServer, customProvider, onNewServerChange, onCustomProviderChange, onAddServer, onClose, error }) {
|
||||
const modalRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (window.Tabler && window.Tabler.Modal && modalRef.current) {
|
||||
const modalInstance = window.Tabler.Modal.getOrCreateInstance(modalRef.current);
|
||||
if (show) {
|
||||
modalInstance.show();
|
||||
} else {
|
||||
modalInstance.hide();
|
||||
}
|
||||
const handler = () => onClose && onClose();
|
||||
modalRef.current.addEventListener('hide.bs.modal', handler);
|
||||
return () => {
|
||||
if (modalRef.current) {
|
||||
modalRef.current.removeEventListener('hide.bs.modal', handler);
|
||||
}
|
||||
};
|
||||
}
|
||||
}, [show, onClose]);
|
||||
|
||||
const handleChange = (field, value) => {
|
||||
onNewServerChange({ ...newServer, [field]: value });
|
||||
};
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
onAddServer();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="modal" tabIndex="-1" ref={modalRef}>
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<h5 className="modal-title">
|
||||
<IconPlus className="icon me-2" />
|
||||
Добавить новый сервер
|
||||
</h5>
|
||||
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
{error && (
|
||||
<div className="alert alert-danger" role="alert">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">IP адрес *</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="192.168.1.1"
|
||||
value={newServer.ip}
|
||||
onChange={(e) => handleChange('ip', e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">DNS имя *</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="srv1.shx.su"
|
||||
value={newServer.dns}
|
||||
onChange={(e) => handleChange('dns', e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Страна *</label>
|
||||
<select
|
||||
className="form-select"
|
||||
value={newServer.country}
|
||||
onChange={(e) => handleChange('country', e.target.value)}
|
||||
required
|
||||
>
|
||||
<option value="">Выберите страну</option>
|
||||
<option value="RU">Россия (RU)</option>
|
||||
<option value="SWE">Швеция (SWE)</option>
|
||||
<option value="US">США (US)</option>
|
||||
<option value="DE">Германия (DE)</option>
|
||||
<option value="NL">Нидерланды (NL)</option>
|
||||
<option value="SG">Сингапур (SG)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Провайдер *</label>
|
||||
<select
|
||||
className="form-select"
|
||||
value={newServer.provider}
|
||||
onChange={(e) => handleChange('provider', e.target.value)}
|
||||
required
|
||||
>
|
||||
<option value="">Выберите провайдера</option>
|
||||
<option value="Yandex">Yandex Cloud</option>
|
||||
<option value="AWS">Amazon Web Services</option>
|
||||
<option value="Google">Google Cloud</option>
|
||||
<option value="Azure">Microsoft Azure</option>
|
||||
<option value="Hetzner">Hetzner</option>
|
||||
<option value="OVH">OVH</option>
|
||||
<option value="DigitalOcean">DigitalOcean</option>
|
||||
<option value="Vultr">Vultr</option>
|
||||
<option value="Linode">Linode</option>
|
||||
<option value="VPSVILLE">VPSVILLE</option>
|
||||
<option value="HIPHOST">HIPHOST</option>
|
||||
<option value="Другой">Другой</option>
|
||||
</select>
|
||||
{newServer.provider === 'Другой' && (
|
||||
<input
|
||||
type="text"
|
||||
className="form-control mt-2"
|
||||
placeholder="Введите название провайдера"
|
||||
value={customProvider}
|
||||
onChange={(e) => onCustomProviderChange(e.target.value)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Тип сервера *</label>
|
||||
<select
|
||||
className="form-select"
|
||||
value={newServer.type}
|
||||
onChange={(e) => handleChange('type', e.target.value)}
|
||||
required
|
||||
>
|
||||
<option value="">Выберите тип</option>
|
||||
{SERVER_TYPE_OPTIONS.map((opt) => (
|
||||
<option key={opt.value} value={opt.value}>{opt.label}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Тип туннеля *</label>
|
||||
<select
|
||||
className="form-select"
|
||||
value={newServer.tunnel}
|
||||
onChange={(e) => handleChange('tunnel', e.target.value)}
|
||||
required
|
||||
>
|
||||
<option value="GRE">GRE (Generic Routing Encapsulation)</option>
|
||||
<option value="IPSec">IPSec</option>
|
||||
<option value="WireGuard">WireGuard</option>
|
||||
<option value="OpenVPN">OpenVPN</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="mb-3">
|
||||
<label className="form-label">Основной шлюз *</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="Cloudflare, Hetzner, Мой шлюз и т.д."
|
||||
value={newServer.gateway}
|
||||
onChange={(e) => handleChange('gateway', e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button type="button" className="btn btn-secondary d-flex align-items-center" data-bs-dismiss="modal">
|
||||
<span className="fw-bold">Отмена</span>
|
||||
</button>
|
||||
<button type="button" className="btn btn-primary d-flex align-items-center" onClick={onAddServer}>
|
||||
<span className="me-2 d-flex align-items-center"><IconPlus className="icon" /></span>
|
||||
<span className="fw-bold">Добавить сервер</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AddServerModal;
|
||||
|
||||
Reference in New Issue
Block a user