Панель экосистемы — лёгкая стартовая страница для быстрого доступа к внутренним сервисам. Древовидная навигация, каталог карточек, поиск, 4 режима отображения, светлая/тёмная тема, настраиваемые узоры и экспорт настроек. Данные и пресеты — через JSON, состояние UI — в localStorage.
Go to file
2026-06-28 18:18:43 +03:00
assets first commit 2026-06-28 18:18:35 +03:00
examples добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00
index.html добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00
panel-data-flat.example.json более гибкая архитектура размещения элементов с примерами и документацией 2026-06-28 18:18:42 +03:00
panel-data-full.example.json более гибкая архитектура размещения элементов с примерами и документацией 2026-06-28 18:18:42 +03:00
panel-data-mixed.example.json более гибкая архитектура размещения элементов с примерами и документацией 2026-06-28 18:18:42 +03:00
panel-data-section-items.example.json более гибкая архитектура размещения элементов с примерами и документацией 2026-06-28 18:18:42 +03:00
panel-data.json вынесение настроек в отдельный файл, добавление readme 2026-06-28 18:18:41 +03:00
README.md добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00
script.js добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00
settings-top-bar.example.json добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00
settings.json добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00
styles.css добавление дефолтных настроек, возможность меню сбоку и сверху 2026-06-28 18:18:43 +03:00

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

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

Стек: 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                           # Данные + пресет UI организации
├── settings-top-bar.example.json           # Пример пресета «шапка сверху»
├── panel-data.json                         # Данные навигации (рабочий файл)
├── examples/                               # Готовые демо-страницы (см. examples/README.md)
│   ├── index.html                          # Оглавление примеров
│   ├── shared/                             # styles, script, assets для демо
│   ├── full/                               # section → group → item
│   ├── section-items/                      # section → item
│   ├── flat/                               # плоский items[]
│   └── mixed/                              # items + groups
├── panel-data-full.example.json            # JSON-сниппет (без страницы)
├── assets/                                 # SVG-иконки сервисов
└── README.md

Конфигурация

settings.json

Указывает, откуда загружать данные панели.

Вариант 1 — загрузка из файла или URL:

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

Можно указать внешний адрес или любой из example-файлов:

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

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

{
  "dataUrl": "",
  "data": {
    "title": "Заголовок панели",
    "sections": []
  }
}

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

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

Пресет организации (defaults + features)

В settings.json можно задать дефолтный вид панели для организации и ограничить, что пользователь может менять в ⚙.

{
  "dataUrl": "./panel-data.json",
  "defaults": {
    "navLayout": "sidebar",
    "theme": "dark",
    "view": "cards",
    "accent": "violet",
    "showNumbers": false,
    "showTreeTags": true,
    "treeTwoColumn": false,
    "autoCollapseSearch": true,
    "sidebarWidth": 390,
    "searchPlaceholder": "Grafana, S3, журнал, сервер..."
  },
  "features": {
    "allowNavLayoutChange": true,
    "allowSearch": true,
    "allowViewChange": true,
    "allowShowNumbers": true,
    "allowTreeOptions": true,
    "allowSidebarResize": true,
    "allowThemeChange": true,
    "allowAccentChange": true
  }
}
defaults Варианты Описание
navLayout "sidebar", "top" "sidebar" — дерево слева; "top" — шапка с названием и поиском, без дерева
theme "dark", "light" Стартовая цветовая тема
view "cards", "list", "compact-cards", "compact-list" Режим отображения каталога
accent "violet", "cyan", "lime", "amber", "custom" Пресет акцента; при "custom" используются поля градиента ниже
customAccentFrom #rrggbb Цвет «от» для accent: "custom" (по умолчанию #8b5cf6)
customAccentTo #rrggbb Цвет «до» для accent: "custom" (по умолчанию #22d3ee)
customAccentAngle 0–360 Угол градиента в градусах (по умолчанию 135)
showNumbers true, false Показывать номера разделов, подразделов и элементов
showTreeTags true, false Теги рядом с элементами в дереве (взаимоисключимо с treeTwoColumn)
treeTwoColumn true, false Элементы папок дерева в 2 колонки (взаимоисключимо с showTreeTags)
autoCollapseSearch true, false При поиске сворачивать ветки дерева без совпадений
sidebarWidth 260–560 (760 при treeTwoColumn: true) Ширина боковой панели в px; игнорируется при navLayout: "top"
searchPlaceholder произвольная строка Текст-подсказка в поле поиска
features Варианты Описание
allowNavLayoutChange true, false Переключатель «Сбоку / Сверху»
allowSearch true, false Поле поиска
allowViewChange true, false Режимы каталога
allowShowNumbers true, false Нумерация
allowTreeOptions true, false Теги, 2 колонки, авто-раскрытие дерева
allowSidebarResize true, false Drag-resize боковой панели
allowThemeChange true, false Светлая / тёмная тема
allowAccentChange true, false Пресеты и свой градиент

Пользовательские изменения сохраняются в localStorage, но заблокированные features всегда возвращаются к defaults.

Пример пресета «только шапка»: settings-top-bar.example.json — navLayout: "top", дерево и resize отключены.

Форматы иерархии

Панель поддерживает три базовых формата. Старый section → group → item работает без изменений.

Формат Структура Дерево Каталог
Полная sections[].groups[].items[] раздел → подраздел → файлы collapsible разделы и подразделы
Раздел → item sections[].items[] раздел → файлы карточки внутри раздела
Плоский список корневой items[] плоский список файлов только сетка карточек
Смешанный sections[].items[] + groups[] прямые файлы, затем подразделы прямые карточки, затем подразделы

Минимум данных: корень должен содержать sections или items. Каждый раздел — groups или items. Каждый элемент — title и type.

Схема panel-data

Абстрактная структура файла данных (без привязки к конкретным сервисам):

{
  "title": "<заголовок панели>",
  "sections": [
    {
      "id": "<slug-раздела>",
      "number": "<опционально>",
      "title": "<название раздела>",
      "description": "<опционально>",
      "items": [
        {
          "id": "<стабильный-ключ>",
          "number": "<опционально>",
          "title": "<название>",
          "type": "<ключ из serviceMeta>",
          "tags": ["<тег>"],
          "url": "<ссылка>"
        }
      ],
      "groups": [
        {
          "id": "<slug-подраздела>",
          "number": "<опционально>",
          "title": "<название подраздела>",
          "description": "<опционально>",
          "items": ["<элементы — та же форма>"]
        }
      ]
    }
  ],
  "items": ["<альтернатива sections: плоский список>"],
  "serviceMeta": {
    "<type-key>": {
      "label": "<подпись типа>",
      "icon": "assets/<иконка>.svg"
    }
  }
}

Используй либо sections, либо корневой items. Внутри раздела — либо groups, либо items, либо оба.

Поля данных

Уровень Поля Описание
Корень title Заголовок панели (sidebar + <title>)
sections Массив разделов (если нет корневого items)
items Плоский список без разделов
serviceMeta Дополнительные или переопределённые типы сервисов
section id, title Обязательные идентификатор и название
number, description Опционально
groups, items Хотя бы одно из двух
group id, title, items Подраздел с элементами
number, description Опционально
item title, type Обязательные название и тип
url Ссылка; "#" — заглушка
tags Массив строк для поиска
id Стабильный ключ (DOM, фокус из дерева)
number Отображаемый номер
  • type — ключ из встроенного defaultServiceMeta или из serviceMeta в JSON
  • id элемента нужен, если нет number — иначе ключ генерируется автоматически

Примеры данных

Готовые демо-страницы — в папке examples/. Корневые panel-data-*.example.json — те же структуры в виде JSON-сниппетов.

Готовые демо-страницы (examples/)

Каждый пример — отдельная страница с index.html, settings.json и panel-data.json. Общие ресурсы в examples/shared/.

cd examples
npx serve .
Путь Формат
/ оглавление примеров
/full/ section → group → item
/section-items/ section → item
/flat/ плоский items[]
/mixed/ items + groups в разделе

Подробнее: examples/README.md.

Типы сервисов (serviceMeta)

Базовые типы заданы в script.js (defaultServiceMeta):

ceph, cloudbeaver, config, gitea, grafana, ipmi, kubernetes, ldap, messages, opensearch, postgresql, prometheus, rabbitmq, redmine, rules, xpath, xmpp

Переопределение или добавление типов в JSON:

{
  "serviceMeta": {
    "my-type": {
      "label": "Подпись",
      "icon": "assets/config.svg"
    }
  }
}

Рекомендуемые типы сервисов

Популярные type, которые можно добавить в serviceMeta (иконки — переиспользовать из assets/):

Категория Типы (type) Комментарий
Прокси / балансировка nginx, traefik reverse proxy, ingress
Контейнеры docker, portainer, argocd runtime, UI, GitOps
CI/CD jenkins, gitlab, harbor сборка, репозиторий, registry
Базы данных mysql, mongodb, redis рядом с уже имеющимися postgresql, opensearch
Очереди / стриминг kafka аналог rabbitmq
Мониторинг / логи loki, zabbix, sentry логи, метрики, ошибки
Безопасность / IAM vault, keycloak, consul секреты, SSO, service mesh
Поиск elasticsearch, sonarqube полнотекст, качество кода
Хранилище minio S3-совместимое
IaC terraform инфраструктура как код
Трекеры jira задачи, рядом с redmine

Чтобы подключить тип:

  1. Добавь запись в serviceMeta вашего JSON или в defaultServiceMeta в script.js
  2. При необходимости положи отдельную SVG в assets/
  3. Укажи "type": "nginx" (и т.д.) в элементах

Настройки интерфейса (⚙)

Popup сгруппирован по разделам. Доступные блоки зависят от features в settings.json. Изменения пользователя сохраняются в localStorage (ecosystem-panel-preferences).

Раздел Настройки
Макет Панель навигации: Сбоку (дерево + поиск) или Сверху (только название и поиск)
Каталог Вид карточек, нумерация
Дерево Теги, 2 колонки, авто-раскрытие поиска (только при navLayout: sidebar)
Оформление Тема, акцент, свой градиент

Режим «Сверху»

Компактная шапка над каталогом: заголовок панели, поиск и ⚙. Дерево навигации скрыто — переход только через карточки каталога. Подходит для простых порталов и когда дерево избыточно.

Свой градиент

Кнопка «Свой» открывает настройки:

  • угол (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 (или свой JSON из dataUrl)
  2. Найди нужный раздел / подраздел или добавь в items / корневой items
  3. Добавь объект с полями title, type, при необходимости tags, url, id, number
  4. Обнови страницу

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

  1. Положи SVG в assets/ (или переиспользуй существующую)
  2. Зарегистрируй тип в serviceMeta JSON или в defaultServiceMeta в script.js

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

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

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

Ограничения

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

Лицензия

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