universal-dashboard/README.md

9.6 KiB
Raw Blame History

Панель экосистемы

Статическая навигационная панель для быстрого доступа к сервисам инфраструктуры. Поддерживает иерархию раздел → подраздел → элемент, поиск, дерево навигации, несколько режимов отображения и настройку внешнего вида.

Стек: HTML, CSS, vanilla JavaScript. Без сборщиков и фреймворков.

Возможности

  • Древовидная навигация слева в стиле файлового менеджера
  • Каталог карточек справа с collapsible-разделами
  • Поиск по названию, тегам, типу сервиса и родительским разделам
  • 4 режима отображения: плитки, список, компактные плитки, компактный список
  • Темы: светлая / тёмная, 4 пресета акцента + свой градиент
  • Настройки через popup (иконка ⚙)
  • Изменяемая ширина бокового меню (drag)
  • Сохранение состояния в localStorage (настройки UI, раскрытие веток)
  • Конфигурация через JSON — локальный объект или загрузка по URL

Быстрый старт

Панель использует fetch, поэтому её нужно открывать через HTTP-сервер, а не напрямую как file://.

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:

{
  "dataUrl": "./panel-data.json"
}

Можно указать внешний адрес:

{
  "dataUrl": "https://example.com/ecosystem/panel-data.json"
}

Вариант 2 — inline-объект в том же файле:

{
  "dataUrl": "",
  "data": {
    "title": "Панель экосистемы",
    "sections": []
  }
}

Если dataUrl не пустой, он имеет приоритет над полем data.

При ошибке загрузки или невалидном JSON на странице показывается экран с описанием проблемы.

panel-data.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 можно добавить или переопределить типы:

{
  "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:
{
  "number": "2.5.3",
  "title": "Новый сервис",
  "type": "gitea",
  "tags": ["gitea", "новый"],
  "url": "https://gitea.example.com"
}
  1. Обнови страницу

Добавить новую иконку

  1. Положи SVG в assets/
  2. Зарегистрируй тип в serviceMeta внутри panel-data.json или используй существующий type

Внешний источник данных

Укажи URL в settings.json:

{
  "dataUrl": "https://your-server/panel-data.json"
}

Убедись, что сервер отдаёт корректный Content-Type: application/json и разрешает CORS, если домен отличается от панели.

Ограничения

  • Требуется HTTP-сервер (fetch не работает с file://)
  • Внешний dataUrl должен быть доступен по CORS
  • Настройки UI хранятся локально в браузере и не синхронизируются между устройствами

Лицензия

Приватный проект. Используй и изменяй по своему усмотрению.