256 lines
9.6 KiB
Markdown
256 lines
9.6 KiB
Markdown
# Панель экосистемы
|
||
|
||
Статическая навигационная панель для быстрого доступа к сервисам инфраструктуры. Поддерживает иерархию **раздел → подраздел → элемент**, поиск, дерево навигации, несколько режимов отображения и настройку внешнего вида.
|
||
|
||
Стек: HTML, CSS, vanilla JavaScript. Без сборщиков и фреймворков.
|
||
|
||
## Возможности
|
||
|
||
- **Древовидная навигация** слева в стиле файлового менеджера
|
||
- **Каталог карточек** справа с collapsible-разделами
|
||
- **Поиск** по названию, тегам, типу сервиса и родительским разделам
|
||
- **4 режима отображения**: плитки, список, компактные плитки, компактный список
|
||
- **Темы**: светлая / тёмная, 4 пресета акцента + свой градиент
|
||
- **Настройки** через popup (иконка ⚙)
|
||
- **Изменяемая ширина** бокового меню (drag)
|
||
- **Сохранение состояния** в `localStorage` (настройки UI, раскрытие веток)
|
||
- **Конфигурация через JSON** — локальный объект или загрузка по URL
|
||
|
||
## Быстрый старт
|
||
|
||
Панель использует `fetch`, поэтому её нужно открывать через HTTP-сервер, а не напрямую как `file://`.
|
||
|
||
```bash
|
||
cd ecosystem
|
||
npx serve .
|
||
```
|
||
|
||
Открой в браузере адрес, который покажет сервер (обычно `http://localhost:3000`).
|
||
|
||
## Структура проекта
|
||
|
||
```
|
||
ecosystem/
|
||
├── index.html # Разметка страницы
|
||
├── styles.css # Стили, темы, адаптив
|
||
├── script.js # Логика, рендер, настройки
|
||
├── settings.json # Источник данных панели (URL или inline)
|
||
├── panel-data.json # Данные навигации (по умолчанию)
|
||
├── assets/ # SVG-иконки сервисов
|
||
└── README.md
|
||
```
|
||
|
||
## Конфигурация
|
||
|
||
### `settings.json`
|
||
|
||
Указывает, откуда загружать данные панели.
|
||
|
||
**Вариант 1 — загрузка из файла или URL:**
|
||
|
||
```json
|
||
{
|
||
"dataUrl": "./panel-data.json"
|
||
}
|
||
```
|
||
|
||
Можно указать внешний адрес:
|
||
|
||
```json
|
||
{
|
||
"dataUrl": "https://example.com/ecosystem/panel-data.json"
|
||
}
|
||
```
|
||
|
||
**Вариант 2 — inline-объект в том же файле:**
|
||
|
||
```json
|
||
{
|
||
"dataUrl": "",
|
||
"data": {
|
||
"title": "Панель экосистемы",
|
||
"sections": []
|
||
}
|
||
}
|
||
```
|
||
|
||
> Если `dataUrl` не пустой, он имеет **приоритет** над полем `data`.
|
||
|
||
При ошибке загрузки или невалидном JSON на странице показывается экран с описанием проблемы.
|
||
|
||
### `panel-data.json`
|
||
|
||
Основной файл с содержимым панели.
|
||
|
||
```json
|
||
{
|
||
"title": "Панель экосистемы",
|
||
"sections": [
|
||
{
|
||
"id": "user",
|
||
"number": "1",
|
||
"title": "Интерфейс пользователя",
|
||
"description": "Описание раздела",
|
||
"groups": [
|
||
{
|
||
"id": "message-filtering",
|
||
"number": "1.1",
|
||
"title": "Управление фильтрацией",
|
||
"description": "Описание подраздела",
|
||
"items": [
|
||
{
|
||
"number": "1.1.1",
|
||
"title": "Редактирование правил",
|
||
"type": "rules",
|
||
"tags": ["правила", "фильтрация"],
|
||
"url": "https://rules.example.com"
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"serviceMeta": {}
|
||
}
|
||
```
|
||
|
||
### Поля данных
|
||
|
||
| Уровень | Поля | Описание |
|
||
|---------|------|----------|
|
||
| **Корень** | `title` | Заголовок панели (sidebar + `<title>`) |
|
||
| | `sections` | Массив разделов |
|
||
| | `serviceMeta` | Опционально: доп. типы сервисов |
|
||
| **section** | `id`, `number`, `title`, `description`, `groups` | Крупный раздел |
|
||
| **group** | `id`, `number`, `title`, `description`, `items` | Подраздел |
|
||
| **item** | `number`, `title`, `type`, `tags`, `url` | Кликабельный элемент |
|
||
|
||
- `type` — ключ из `serviceMeta` (определяет иконку и подпись типа)
|
||
- `tags` — используются в поиске и опционально в дереве
|
||
- `url` — ссылка перехода; `"#"` означает заглушку (клик не ведёт никуда)
|
||
|
||
### Типы сервисов (`serviceMeta`)
|
||
|
||
Базовые типы заданы в `script.js`:
|
||
|
||
`ceph`, `cloudbeaver`, `config`, `gitea`, `grafana`, `ipmi`, `kubernetes`, `ldap`, `messages`, `opensearch`, `postgresql`, `prometheus`, `rabbitmq`, `redmine`, `rules`, `xpath`, `xmpp`
|
||
|
||
В `panel-data.json` можно добавить или переопределить типы:
|
||
|
||
```json
|
||
{
|
||
"serviceMeta": {
|
||
"my-service": {
|
||
"label": "My Service",
|
||
"icon": "assets/config.svg"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## Настройки интерфейса (⚙)
|
||
|
||
Доступны в popup-окне и сохраняются в `localStorage` (`ecosystem-panel-preferences`):
|
||
|
||
| Настройка | Описание |
|
||
|-----------|----------|
|
||
| **Тема** | Светлая / тёмная |
|
||
| **Вид** | Плитки, список, компакт плитки, компакт список |
|
||
| **Нумерация** | Показывать номера разделов, подразделов и элементов |
|
||
| **Теги дерева** | Поисковые теги рядом с элементами в дереве |
|
||
| **2 колонки в дереве** | Элементы папок в 2 колонки (взаимоисключимо с тегами) |
|
||
| **Авто раскрывать поиск** | При поиске сворачивать ветки без совпадений |
|
||
| **Акцент** | violet, cyan, lime, amber или свой градиент |
|
||
|
||
### Свой градиент
|
||
|
||
Кнопка **«Свой»** открывает настройки:
|
||
|
||
- угол (0–360°)
|
||
- цвет «от» и «до»
|
||
|
||
Значения сохраняются в `localStorage`.
|
||
|
||
## Поведение интерфейса
|
||
|
||
### Поиск
|
||
|
||
Фильтрует каталог и подсвечивает совпадения в дереве и карточках. Ищет по:
|
||
|
||
- названию элемента
|
||
- номеру
|
||
- тегам
|
||
- типу сервиса
|
||
- названиям родительских разделов
|
||
|
||
### Дерево навигации
|
||
|
||
- Клик по **папке** — раскрытие/сворачивание
|
||
- Клик по **названию** — прокрутка к элементу в каталоге
|
||
- Состояние раскрытия сохраняется отдельно для дерева и контента (`ecosystem-panel-collapse-state`)
|
||
|
||
### Адаптив
|
||
|
||
- **Touch-устройства** (`pointer: coarse` / `hover: none`): stacked-layout, меню сверху
|
||
- **Мышь** (`pointer: fine` + `hover: hover`): sidebar + resizer + каталог в колонках
|
||
- **2 колонки в дереве на touch**: в portrait или при ширине от 520px
|
||
|
||
### Ширина layout
|
||
|
||
- Обычный режим: max **1560px**, sidebar до **560px**
|
||
- Режим «2 колонки в дереве»: max **1920px**, sidebar до **760px**
|
||
|
||
## localStorage
|
||
|
||
| Ключ | Содержимое |
|
||
|------|------------|
|
||
| `ecosystem-panel-preferences` | Тема, акцент, вид, ширина sidebar, toggle-настройки |
|
||
| `ecosystem-panel-collapse-state` | Раскрытые/свернутые ветки дерева и каталога |
|
||
|
||
## Разработка
|
||
|
||
### Добавить новый элемент
|
||
|
||
1. Открой `panel-data.json`
|
||
2. Найди нужный `group` в `sections`
|
||
3. Добавь объект в `items`:
|
||
|
||
```json
|
||
{
|
||
"number": "2.5.3",
|
||
"title": "Новый сервис",
|
||
"type": "gitea",
|
||
"tags": ["gitea", "новый"],
|
||
"url": "https://gitea.example.com"
|
||
}
|
||
```
|
||
|
||
4. Обнови страницу
|
||
|
||
### Добавить новую иконку
|
||
|
||
1. Положи SVG в `assets/`
|
||
2. Зарегистрируй тип в `serviceMeta` внутри `panel-data.json` или используй существующий `type`
|
||
|
||
### Внешний источник данных
|
||
|
||
Укажи URL в `settings.json`:
|
||
|
||
```json
|
||
{
|
||
"dataUrl": "https://your-server/panel-data.json"
|
||
}
|
||
```
|
||
|
||
Убедись, что сервер отдаёт корректный `Content-Type: application/json` и разрешает CORS, если домен отличается от панели.
|
||
|
||
## Ограничения
|
||
|
||
- Требуется HTTP-сервер (`fetch` не работает с `file://`)
|
||
- Внешний `dataUrl` должен быть доступен по CORS
|
||
- Настройки UI хранятся локально в браузере и не синхронизируются между устройствами
|
||
|
||
## Лицензия
|
||
|
||
Приватный проект. Используй и изменяй по своему усмотрению.
|