feat: Add comprehensive documentation for Router Lists UI, including setup instructions, API endpoints, and frontend/backend structure; enhance navbar styles for better responsiveness
Publish Fast Tabler Docker image / build-and-push-fast (push) Has been cancelled
Publish Fast Tabler Docker image / build-and-push-fast (push) Has been cancelled
This commit is contained in:
@@ -1,3 +1,115 @@
|
||||
# Router Lists UI
|
||||
|
||||
Полноценный UI/Backend для управления списками BGP (домены, IP-диапазоны, ASNs), фильтрами и конфигурациями MikroTik на базе S3 (Yandex Object Storage). Интерфейс построен на Tabler, frontend — Vite + React, backend — Express.
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### Требования
|
||||
- Node.js 18+
|
||||
- S3-совместимое хранилище (Yandex Object Storage)
|
||||
- Доступы AWS: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `S3_BUCKET_NAME`, `AWS_REGION`
|
||||
|
||||
### Запуск backend
|
||||
```bash
|
||||
cd backend
|
||||
npm i
|
||||
cp .env.example .env # заполните переменные
|
||||
npm start
|
||||
```
|
||||
Сервис поднимется на `http://localhost:3001`.
|
||||
|
||||
### Запуск frontend
|
||||
```bash
|
||||
cd frontend
|
||||
npm i
|
||||
npm run dev
|
||||
```
|
||||
Frontend доступен на `http://localhost:5173` (по умолчанию). Production-сборка: `npm run build`.
|
||||
|
||||
## Главные особенности
|
||||
- Единая UX/UI библиотека Tabler, адаптивные панели действий и навигация.
|
||||
- Онлайн-обновление (WebSocket) BGP c потоковым логом и фоновое обновление (HTTP POST) из UI.
|
||||
- Блокировки (soft-lock) ресурсов с TTL, чтобы избежать гонок при одновременном редактировании.
|
||||
- Версионирование данных (история/откат), если включено версии в бакете.
|
||||
- Генерация конфигурации MikroTik из фильтров (`/api/filters/generate-config`) и экспорт в S3.
|
||||
- Метрики Prometheus: `/metrics`, health/ready: `/health`, `/ready`.
|
||||
|
||||
## API (backend)
|
||||
|
||||
Все ответы об ошибке имеют единый формат:
|
||||
```json
|
||||
{ "code": "E_*", "message": "...", "details": {}, "requestId": "..." }
|
||||
```
|
||||
Успешные POST/PUT возвращают:
|
||||
```json
|
||||
{ "ok": true, "etag": "...", "lastModified": "ISO", "contentLength": 123 }
|
||||
```
|
||||
И всегда выставляют заголовки `ETag`, `Last-Modified`, `Content-Length-Source` (если есть). GET поддерживают `countOnly=true` там, где это логично.
|
||||
|
||||
### Данные
|
||||
- GET `/api/domains-new` — список доменов `{ domain, community }`
|
||||
- `?q=`, `?offset=`, `?limit=`, `?countOnly=true`, `?format=std`
|
||||
- POST `/api/domains-new` — `{ domains: [{domain, community}], etag }`
|
||||
|
||||
- GET `/api/ip-ranges` — список `[{ ipRange, community }]`
|
||||
- POST `/api/ip-ranges` — `{ ipRanges: [{ipRange, community}], etag }`
|
||||
|
||||
- GET `/api/asns` — список `[{ domain, type }]` (domain = AS, type = community)
|
||||
- POST `/api/asns` — `{ domains: [{domain, type}], etag }`
|
||||
|
||||
- GET `/api/communities` — справочник community (JSON)
|
||||
- POST `/api/communities` — `{ communities: [...] }` (валидация уникальности value)
|
||||
|
||||
### Фильтры и конфигурации
|
||||
- GET `/api/filters` / POST `/api/filters` — фильтры для всех серверов.
|
||||
- GET `/api/filters/generate-config` — сгенерировать конфиг MikroTik из `filters.json`.
|
||||
- POST `/api/filters/export-config` — сохранить сгенерированный конфиг в S3 (`mikrotik-frouting-config.txt`).
|
||||
|
||||
- GET `/api/server-configs` / POST `/api/server-configs` — список серверов (id, name, ...).
|
||||
- GET `/api/server-configs/:serverId` / POST `/api/server-configs/:serverId` — конфиг конкретного сервера.
|
||||
- DELETE `/api/server-configs/:serverId` — удалить конфиг.
|
||||
- DELETE `/api/server-configs/:serverId/complete` — удалить конфиг и фильтры.
|
||||
|
||||
- GET `/api/server-filters/:serverId` — фильтры сервера.
|
||||
- POST `/api/server-filters/:serverId` — сохранить фильтры сервера.
|
||||
- POST `/api/server-filters/generate-config` — сгенерировать конфиг MikroTik на лету из переданных `{ filters }`.
|
||||
|
||||
### Прочее
|
||||
- GET `/api/servers` / POST `/api/servers` — список серверов.
|
||||
- GET `/api/billing` / POST `/api/billing` — биллинг (ноды, статусы и т.п.).
|
||||
- GET `/api/auto-urls` / POST `/api/auto-urls` — список авто-URL.
|
||||
- POST `/api/auto-urls/process` — обработать авто-URL и добавить IP в `bgp_data/ips.txt`.
|
||||
- GET `/api/servers/availability?ttlSeconds=60` — быстрый TCP‑чек доступности нод.
|
||||
- GET `/api/s3/last-modified` — метаданные S3 (etag/lastModified/contentLength) по ключевым файлам.
|
||||
- Locks: GET `/api/locks/:resource`, POST `/api/locks/:resource`, DELETE `/api/locks/:resource`.
|
||||
- History: GET `/api/history/:resource`, POST `/api/history/:resource/rollback`.
|
||||
|
||||
## Frontend
|
||||
- Vite + React, Tabler CSS/JS (`@tabler/core`).
|
||||
- Общий компонент `PageHeaderActions` — единый toolbar на страницах данных.
|
||||
- Модалка `WsUpdateModal` — поток логов online-обновления (ws).
|
||||
- Доступность: роли, подписи, фокус-кольца, hot-path без мыши.
|
||||
|
||||
### Скрипты
|
||||
```bash
|
||||
npm run dev # dev-сервер
|
||||
npm run build # продакшн сборка
|
||||
```
|
||||
|
||||
## Структура репозитория
|
||||
```
|
||||
backend/ # Express API
|
||||
frontend/ # Vite React UI
|
||||
```
|
||||
|
||||
## Безопасность и эксплуатация
|
||||
- Helmet, RateLimit, CORS, отключён слабый etag на JSON.
|
||||
- Prometheus метрики по умолчанию.
|
||||
- Для истории версий включите versioning в бакете S3.
|
||||
|
||||
## Лицензия
|
||||
MIT
|
||||
|
||||
# 📂 S3 Lists Manager
|
||||
|
||||
|
||||
|
||||
@@ -167,12 +167,13 @@
|
||||
.navbar-nav .dropdown-menu {
|
||||
position: static;
|
||||
float: none;
|
||||
width: auto;
|
||||
margin-top: 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
width: 100%;
|
||||
margin-top: 0.25rem;
|
||||
background-color: var(--tblr-bg-surface);
|
||||
border: 1px solid var(--tblr-border-color);
|
||||
box-shadow: 0 0.25rem 0.5rem rgba(0,0,0,0.08);
|
||||
}
|
||||
.navbar-nav .dropdown-item { padding: 0.5rem 0.75rem; }
|
||||
}
|
||||
|
||||
/* Custom animations */
|
||||
|
||||
+15
-1
@@ -75,6 +75,7 @@ import {
|
||||
useLocation,
|
||||
Navigate
|
||||
} from 'react-router-dom';
|
||||
import { IconMenu2 } from '@tabler/icons-react';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
@@ -208,6 +209,19 @@ function MainLayout() {
|
||||
<span className="fw-bold">S3 Lists Manager</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Кнопка бургера для мобильных */}
|
||||
<button
|
||||
className="navbar-toggler d-md-none"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbar-menu"
|
||||
aria-controls="navbar-menu"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<IconMenu2 />
|
||||
</button>
|
||||
|
||||
{/* Основное меню */}
|
||||
<div className="collapse navbar-collapse" id="navbar-menu">
|
||||
@@ -264,7 +278,7 @@ function MainLayout() {
|
||||
</div>
|
||||
|
||||
{/* Правая часть навбара: язык и тема */}
|
||||
<div className="navbar-nav flex-row order-md-last">
|
||||
<div className="navbar-nav flex-row order-md-last ms-2">
|
||||
<div className="nav-item me-2">
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
|
||||
@@ -26,7 +26,7 @@ function PageHeaderActions({
|
||||
onBackgroundUpdate,
|
||||
}) {
|
||||
return (
|
||||
<div className="header-actions">
|
||||
<div className="header-actions" role="toolbar" aria-label="Действия страницы">
|
||||
<div className="btn-group">
|
||||
{onOnlineUpdate && (
|
||||
<button className="btn btn-outline-warning" type="button" onClick={onOnlineUpdate} title="Online-обновление BGP (WebSocket)">
|
||||
|
||||
Reference in New Issue
Block a user