docs(ET-002): add ADR-0001 and infra requirements for POI toggle
Record architecture decision to implement POI visibility toggling client-side (setLayoutProperty + localStorage), reusing the existing layerState model, with no backend, DB or infrastructure changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
---
|
||||
type: adr
|
||||
work_item_id: ET-002
|
||||
adr_id: adr-0001
|
||||
title: "ADR-0001: Управление видимостью POI — клиентское решение на localStorage"
|
||||
status: accepted
|
||||
created_at: 2026-05-21
|
||||
authors:
|
||||
- "agent:architect"
|
||||
supersedes: []
|
||||
superseded_by: []
|
||||
labels: []
|
||||
---
|
||||
|
||||
# ADR-0001 — Управление видимостью POI: клиентское решение на localStorage
|
||||
|
||||
## Статус
|
||||
|
||||
Accepted
|
||||
|
||||
## Контекст
|
||||
|
||||
ET-002 добавляет в попап кнопки «Рельеф» (`terrain-popup`) чекбокс «POI»,
|
||||
позволяющий пользователю скрывать маркеры POI (слои `poi-circles`,
|
||||
`poi-labels`), чтобы не загромождать карту при планировании маршрута.
|
||||
|
||||
Существующее состояние кодовой базы (`src/web/app.js`):
|
||||
|
||||
- объект `layerState = { tracks, paths, poi, basemap }` — внутренняя модель
|
||||
видимости слоёв (строка 377), `poi: true` по умолчанию;
|
||||
- карта групп слоёв `poi: ['poi-circles', 'poi-labels']` (строка 381);
|
||||
- функция `toggleLayer(group)` уже переключает видимость через
|
||||
`map.setLayoutProperty(..., 'visibility', ...)` (строки 385–389), но
|
||||
завязана на кнопку-тулбар (`btn.classList.toggle('active', ...)`), а не на
|
||||
чекбокс попапа;
|
||||
- сложился устойчивый паттерн персистентности в `localStorage` со
|
||||
значениями `'1'`/`'0'`: ключи `terrain-hillshade`, `terrain-tri`,
|
||||
`trails-track`, `trails-path`, `enduro-theme-mode`, `MARKERS_KEY`.
|
||||
|
||||
Backend (FastAPI) и БД (SQLite/Spatialite) к видимости POI отношения не
|
||||
имеют — POI отдаются как часть тайлов/источника, видимость регулируется
|
||||
исключительно на уровне рендера MapLibre.
|
||||
|
||||
## Рассматриваемые варианты
|
||||
|
||||
### Вариант A — Клиентское решение: `setLayoutProperty` + `localStorage` (выбран)
|
||||
|
||||
Видимость переключается через `map.setLayoutProperty()` для слоёв
|
||||
`poi-circles` и `poi-labels`; состояние хранится в `localStorage` под
|
||||
ключом `poi-visible`; `layerState.poi` остаётся единственным источником
|
||||
истины в рантайме.
|
||||
|
||||
- **Плюсы:** нулевые изменения backend/БД/инфраструктуры; переключение
|
||||
мгновенное (тайлы не перезагружаются — слой остаётся в источнике,
|
||||
меняется только `layout.visibility`); полностью консистентно с уже
|
||||
существующими чекбоксами попапа и принципом «минимум зависимостей».
|
||||
- **Минусы:** настройка не синхронизируется между устройствами/браузерами
|
||||
(для данной фичи это приемлемо и зафиксировано как Out of scope в BRD).
|
||||
|
||||
### Вариант B — Хранение настройки на backend (профиль пользователя)
|
||||
|
||||
Видимость POI сохраняется через новый API-эндпоинт в SQLite.
|
||||
|
||||
- **Плюсы:** синхронизация между устройствами.
|
||||
- **Минусы:** требует модели пользователя/сессий (в проекте отсутствует),
|
||||
новый эндпоинт, миграцию БД, сетевой round-trip — несопоставимо
|
||||
избыточно для одного UI-флага. Противоречит принципам BRD (минимум
|
||||
зависимостей, нет необходимости в server-state).
|
||||
|
||||
### Вариант C — Удаление/повторное добавление слоёв POI
|
||||
|
||||
Скрытие через `map.removeLayer()`, показ через `map.addLayer()`.
|
||||
|
||||
- **Плюсы:** нет «невидимых» слоёв в стиле.
|
||||
- **Минусы:** дороже по производительности, риск рассинхрона порядка
|
||||
слоёв и обработчиков событий (`map.on('click', 'poi-circles', ...)`,
|
||||
строка 1515), усложняет код. `setLayoutProperty` — штатный механизм
|
||||
MapLibre именно для этого сценария.
|
||||
|
||||
## Решение
|
||||
|
||||
Принимается **Вариант A**.
|
||||
|
||||
1. **Видимость** слоёв `poi-circles` и `poi-labels` переключается через
|
||||
`map.setLayoutProperty(layerId, 'visibility', 'visible' | 'none')`.
|
||||
2. **Персистентность** — `localStorage`, ключ `poi-visible`, значения
|
||||
`'1'` / `'0'`, в соответствии с уже сложившейся конвенцией проекта.
|
||||
3. **Источник истины в рантайме** — `layerState.poi`. Обработчик
|
||||
`onPoiCheckbox()` обязан синхронно обновлять `layerState.poi`,
|
||||
`localStorage` и `layout.visibility` обоих слоёв.
|
||||
4. **Без дублирования логики.** Логика установки видимости группы POI
|
||||
должна переиспользовать существующую карту групп слоёв
|
||||
(`poi: ['poi-circles','poi-labels']`). Допускается выделение общего
|
||||
приватного хелпера (например `applyPoiVisibility(visible)`),
|
||||
вызываемого как из `onPoiCheckbox()`, так и из восстановления
|
||||
состояния при загрузке. `toggleLayer('poi')` (тулбар-кнопка) и
|
||||
`onPoiCheckbox()` (чекбокс попапа) должны оставаться консистентны
|
||||
через общий `layerState.poi` — недопустимо, чтобы кнопка и чекбокс
|
||||
показывали разное состояние.
|
||||
5. **Backend, БД, API, инфраструктура — без изменений.** Состав
|
||||
компонентов C4 не меняется, обновление C4-диаграмм не требуется.
|
||||
|
||||
## Последствия
|
||||
|
||||
### Положительные
|
||||
|
||||
- Изменение полностью клиентское: deploy без миграций и без изменения
|
||||
состава контейнеров.
|
||||
- Переключение < 50 мс (REQ-NF-01) — тайлы не перезагружаются.
|
||||
- Конвенция `localStorage` остаётся единообразной — ниже когнитивная
|
||||
нагрузка при поддержке.
|
||||
|
||||
### Отрицательные / ограничения
|
||||
|
||||
- Настройка локальна для браузера: при очистке `localStorage` или смене
|
||||
устройства сбрасывается на дефолт (POI включены). Принято осознанно.
|
||||
- В стиле карты остаются слои с `visibility: none` — это штатно для
|
||||
MapLibre и не влияет на производительность.
|
||||
|
||||
### Технический долг
|
||||
|
||||
- `toggleLayer()` и `onPoiCheckbox()` частично дублируют намерение
|
||||
«переключить группу слоёв». Если в будущих фазах появятся ещё
|
||||
popup-чекбоксы для слоёв, стоит унифицировать тулбар-кнопки и
|
||||
popup-чекбоксы в единый контроллер слоёв. На ET-002 — вне scope.
|
||||
|
||||
## Классификация изменения
|
||||
|
||||
Minor change. Новые сервисы/БД/эндпоинты не вводятся, состав компонентов
|
||||
не меняется. Лейбл `arch:major-change` **не требуется**. Обязательного
|
||||
архитектурного approve не требуется.
|
||||
|
||||
## Связанные документы
|
||||
|
||||
- `docs/work-items/ET-002/01-brd.md`
|
||||
- `docs/work-items/ET-002/02-trz.md`
|
||||
- `docs/work-items/ET-002/03-acceptance-criteria.md`
|
||||
- `docs/work-items/ET-002/07-infra-requirements.md`
|
||||
- `docs/architecture/README.md`
|
||||
94
docs/work-items/ET-002/07-infra-requirements.md
Normal file
94
docs/work-items/ET-002/07-infra-requirements.md
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
type: infra-requirements
|
||||
work_item_id: ET-002
|
||||
title: "Инфраструктурные требования — ET-002: Чекбокс показа/скрытия POI"
|
||||
version: 1
|
||||
status: approved
|
||||
created_at: 2026-05-21
|
||||
authors:
|
||||
- "agent:architect"
|
||||
---
|
||||
|
||||
# Инфраструктурные требования — ET-002
|
||||
|
||||
## 1. Резюме
|
||||
|
||||
ET-002 — изменение **исключительно фронтенда** (`src/web/index.html`,
|
||||
`src/web/app.js`). Новой инфраструктуры не требуется. Документ
|
||||
зафиксирован для полноты work-item и явно подтверждает отсутствие
|
||||
инфра-воздействия (см. ADR-0001).
|
||||
|
||||
## 2. Контейнеры и сервисы
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые контейнеры | Нет |
|
||||
| Изменения существующих сервисов (api, osrm, nginx) | Нет |
|
||||
| Изменения `docker-compose.yml` | Нет |
|
||||
| Изменения `Dockerfile` | Нет |
|
||||
|
||||
## 3. Сеть
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые порты | Нет |
|
||||
| Изменения reverse proxy (nginx, `/enduro/`) | Нет |
|
||||
| Новые внешние домены / DNS | Нет |
|
||||
| Исходящие сетевые вызовы из фронтенда | Нет (вся логика локальная) |
|
||||
|
||||
## 4. Хранилища данных
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Изменения схемы SQLite/Spatialite | Нет |
|
||||
| Миграции БД (`migrations/`) | Нет |
|
||||
| Серверное хранилище состояния | Нет |
|
||||
| Клиентское хранилище | `localStorage`, ключ `poi-visible` (`'1'`/`'0'`), ≈ 1 байт полезной нагрузки на браузер |
|
||||
|
||||
## 5. Конфигурация и секреты
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые переменные окружения | Нет |
|
||||
| Новые секреты | Нет |
|
||||
| Изменения конфигурации FastAPI / uvicorn | Нет |
|
||||
|
||||
## 6. Зависимости
|
||||
|
||||
| Аспект | Требование |
|
||||
|--------|------------|
|
||||
| Новые npm/Python пакеты | Нет |
|
||||
| Новые внешние сервисы | Нет |
|
||||
| Версия MapLibre GL JS | Без изменений (`setLayoutProperty` — штатный API) |
|
||||
|
||||
## 7. Сборка и деплой
|
||||
|
||||
- **Pipeline:** существующий Gitea Actions без изменений (`lint`, `test`,
|
||||
`build`).
|
||||
- **Артефакт:** статические ассеты фронтенда (`src/web/`). Деплой —
|
||||
штатная пересборка/перевыкладка и `docker compose up -d` на mva154.
|
||||
- **Простой (downtime):** нет — изменение только в статике фронтенда.
|
||||
- **План отката:** обратный коммит (revert) и повторный деплой;
|
||||
миграций/состояния, требующих отдельного отката, нет.
|
||||
|
||||
## 8. Ресурсы (CPU / RAM / диск)
|
||||
|
||||
Воздействие отсутствует. Переключение `layout.visibility` слоёв
|
||||
выполняется в браузере клиента; тайлы не перезапрашиваются (REQ-NF-01).
|
||||
|
||||
## 9. Наблюдаемость
|
||||
|
||||
Новые метрики, логи и алерты не требуются. Поведение проверяется
|
||||
e2e-тестами фронтенда согласно `04-test-plan.yaml`.
|
||||
|
||||
## 10. Влияние на C4
|
||||
|
||||
Состав компонентов системы не меняется. Обновление
|
||||
`docs/architecture/c4-*.mmd` не требуется (диаграммы C4 в репозитории
|
||||
на данный момент отсутствуют — только `docs/architecture/README.md`).
|
||||
|
||||
## 11. Вывод
|
||||
|
||||
Инфраструктурных, сетевых, конфигурационных изменений и изменений БД
|
||||
**нет**. ET-002 безопасен для деплоя в рамках обычного релизного цикла
|
||||
фронтенда. Эскалация `arch:major-change` не требуется.
|
||||
Reference in New Issue
Block a user