universal-dashboard/README.md

256 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Панель экосистемы
Статическая навигационная панель для быстрого доступа к сервисам инфраструктуры. Поддерживает иерархию **раздел → подраздел → элемент**, поиск, дерево навигации, несколько режимов отображения и настройку внешнего вида.
Стек: 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 хранятся локально в браузере и не синхронизируются между устройствами
## Лицензия
Приватный проект. Используй и изменяй по своему усмотрению.