feat: Добавить анимации и улучшения UX/UI в компоненты приложения, включая плавные переходы, эффекты при наведении и анимации для модальных окон. Обновить карточки и таблицы с новыми анимациями для улучшения визуального восприятия и доступности.
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m42s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 2m42s
This commit is contained in:
+136
-14
@@ -1,6 +1,9 @@
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import api from './lib/api.js';
|
||||
import ConfirmDialog from './components/ConfirmDialog.jsx';
|
||||
import FormModal from './components/FormModal.jsx';
|
||||
import ConfirmModal from './components/ConfirmModal.jsx';
|
||||
import FormField from './components/FormField.jsx';
|
||||
import {
|
||||
IconPlus,
|
||||
IconSearch,
|
||||
@@ -18,7 +21,8 @@ import {
|
||||
IconChevronDown,
|
||||
IconLink,
|
||||
IconFilter,
|
||||
IconMapPin
|
||||
IconMapPin,
|
||||
IconWorld
|
||||
} from '@tabler/icons-react';
|
||||
import GraphView from './GraphView';
|
||||
|
||||
@@ -691,12 +695,23 @@ function ServerManager() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Delete Modal */}
|
||||
<DeleteServerModal
|
||||
{/* Delete Modal - New unified component */}
|
||||
<ConfirmModal
|
||||
show={showDeleteModal}
|
||||
server={serverToDelete}
|
||||
onDelete={executeDelete}
|
||||
onClose={() => setShowDeleteModal(false)}
|
||||
onConfirm={executeDelete}
|
||||
title="Подтверждение удаления"
|
||||
message={
|
||||
serverToDelete ? (
|
||||
<>
|
||||
<p>Вы уверены, что хотите удалить сервер <strong>{serverToDelete.ip}</strong>?</p>
|
||||
<p className="text-muted mb-0">Это действие нельзя отменить.</p>
|
||||
</>
|
||||
) : null
|
||||
}
|
||||
confirmLabel="Удалить"
|
||||
variant="danger"
|
||||
icon={IconTrash}
|
||||
/>
|
||||
|
||||
{/* Edit Server Modal */}
|
||||
@@ -719,17 +734,124 @@ function ServerManager() {
|
||||
onClose={handleLinkGeneratorClose}
|
||||
/>
|
||||
|
||||
{/* Add Server Modal */}
|
||||
<AddServerModal
|
||||
{/* Add Server Modal - New unified component */}
|
||||
<FormModal
|
||||
show={addServerModalOpen}
|
||||
newServer={newServer}
|
||||
customProvider={customProvider}
|
||||
onNewServerChange={setNewServer}
|
||||
onCustomProviderChange={setCustomProvider}
|
||||
onAddServer={handleAddServerFromModal}
|
||||
onClose={handleCloseAddServerModal}
|
||||
error={error}
|
||||
/>
|
||||
onSubmit={handleAddServerFromModal}
|
||||
title="Добавить новый сервер"
|
||||
submitLabel="Добавить сервер"
|
||||
submitIcon={IconPlus}
|
||||
size="md"
|
||||
>
|
||||
{error && (
|
||||
<div className="alert alert-danger mb-3" role="alert">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
label="IP адрес"
|
||||
name="ip"
|
||||
value={newServer.ip}
|
||||
onChange={(val) => setNewServer({ ...newServer, ip: val })}
|
||||
placeholder="192.168.1.1"
|
||||
required
|
||||
icon={IconServer}
|
||||
helpText="Введите IPv4 адрес сервера"
|
||||
/>
|
||||
|
||||
<FormField
|
||||
label="DNS имя"
|
||||
name="dns"
|
||||
value={newServer.dns}
|
||||
onChange={(val) => setNewServer({ ...newServer, dns: val })}
|
||||
placeholder="srv1.shx.su"
|
||||
required
|
||||
icon={IconWorld}
|
||||
helpText="Полное доменное имя сервера"
|
||||
/>
|
||||
|
||||
<FormField
|
||||
label="Страна"
|
||||
name="country"
|
||||
type="select"
|
||||
value={newServer.country}
|
||||
onChange={(val) => setNewServer({ ...newServer, country: val })}
|
||||
required
|
||||
icon={IconMapPin}
|
||||
options={[
|
||||
{ value: '', label: 'Выберите страну', disabled: true },
|
||||
{ value: 'RU', label: 'Россия (RU)' },
|
||||
{ value: 'SWE', label: 'Швеция (SWE)' },
|
||||
{ value: 'US', label: 'США (US)' },
|
||||
{ value: 'DE', label: 'Германия (DE)' },
|
||||
{ value: 'NL', label: 'Нидерланды (NL)' },
|
||||
{ value: 'SG', label: 'Сингапур (SG)' }
|
||||
]}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
label="Провайдер"
|
||||
name="provider"
|
||||
type="select"
|
||||
value={newServer.provider}
|
||||
onChange={(val) => setNewServer({ ...newServer, provider: val })}
|
||||
required
|
||||
options={[
|
||||
{ value: '', label: 'Выберите провайдера', disabled: true },
|
||||
{ value: 'Yandex', label: 'Yandex Cloud' },
|
||||
{ value: 'AWS', label: 'Amazon Web Services' },
|
||||
{ value: 'Google', label: 'Google Cloud' },
|
||||
{ value: 'Azure', label: 'Microsoft Azure' },
|
||||
{ value: 'Hetzner', label: 'Hetzner' },
|
||||
{ value: 'OVH', label: 'OVH' },
|
||||
{ value: 'DigitalOcean', label: 'DigitalOcean' },
|
||||
{ value: 'Vultr', label: 'Vultr' },
|
||||
{ value: 'Linode', label: 'Linode' },
|
||||
{ value: 'VPSVILLE', label: 'VPSVILLE' },
|
||||
{ value: 'HIPHOST', label: 'HIPHOST' },
|
||||
{ value: 'Другой', label: 'Другой' }
|
||||
]}
|
||||
/>
|
||||
|
||||
{newServer.provider === 'Другой' && (
|
||||
<FormField
|
||||
label="Название провайдера"
|
||||
name="customProvider"
|
||||
value={customProvider}
|
||||
onChange={setCustomProvider}
|
||||
placeholder="Введите название провайдера"
|
||||
required
|
||||
helpText="Укажите название вашего провайдера"
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
label="Тип туннеля"
|
||||
name="tunnel"
|
||||
type="select"
|
||||
value={newServer.tunnel}
|
||||
onChange={(val) => setNewServer({ ...newServer, tunnel: val })}
|
||||
required
|
||||
options={[
|
||||
{ value: 'GRE', label: 'GRE (Generic Routing Encapsulation)' },
|
||||
{ value: 'IPSec', label: 'IPSec' },
|
||||
{ value: 'WireGuard', label: 'WireGuard' },
|
||||
{ value: 'OpenVPN', label: 'OpenVPN' }
|
||||
]}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
label="Основной шлюз"
|
||||
name="gateway"
|
||||
value={newServer.gateway}
|
||||
onChange={(val) => setNewServer({ ...newServer, gateway: val })}
|
||||
placeholder="Cloudflare, Hetzner, Мой шлюз и т.д."
|
||||
required
|
||||
helpText="Имя основного шлюза для маршрутизации"
|
||||
/>
|
||||
</FormModal>
|
||||
|
||||
<div className="card w-100 mb-4">
|
||||
<div className="card-header d-flex justify-content-between align-items-center">
|
||||
|
||||
Reference in New Issue
Block a user