Files
enduro-trails/docs/work-items/ET-014/08-data-requirements.md
claude-bot bc63122221
All checks were successful
CI / lint (push) Successful in 5s
CI / test (push) Successful in 10s
CI / build (push) Successful in 2s
architect(ET): auto-commit from architect run_id=88
2026-06-04 11:15:52 +00:00

265 lines
16 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.
---
type: data-requirements
work_item_id: ET-014
title: "Требования к данным — ET-014: Z-index фикс — terrain-popup уступает sheet'у"
version: 1
status: approved
created_at: 2026-06-04
authors:
- "agent:architect"
---
# Требования к данным — ET-014
## 1. Резюме
ET-014 — **pure client UI ordering change**. Никаких изменений в данных:
ни в БД, ни в файлах на диске, ни в localStorage, ни в API-контрактах,
ни в конфигурациях.
Меняется **порядок вызова двух уже существующих UI-функций** в
`src/web/app.js`: при открытии любого `.bottom-sheet` теперь
принудительно вызывается helper `closeTerrainPopup()`, который скрывает
`#terrain-popup` (если он открыт) и снимает класс `.active` с
`#terrain-toggle`.
**Меняется:**
- Порядок DOM-операций при `openSheet(id)` (1 дополнительный вызов).
- Видимое состояние `#terrain-popup` в момент открытия любого
bottom-sheet (теперь скрывается; раньше оставался открытым → визуальный
баг ET-014).
**Не меняется:**
- Содержимое и схема БД `centralfederal.sqlite`, `gps_tracks.sqlite`.
- Содержимое и формат PNG-тайлов в `data/terrain/*`.
- Контракты API (`/api/gps-tracks/*`, `/terrain/*`, `/api/route/*`,
`/api/health`, прочие).
- Ключи `localStorage` (`terrain-hillshade`, `terrain-tri`,
`gps-tracks-enabled`, gps-фильтры, theme, units и т. д.).
- `style.json`, `style-dark.json`.
- `config/*.yaml`.
- `src/web/index.html`, `src/web/gps_tracks.js`, `src/web/app.css`.
## 2. Архитектурные границы данных
| Слой данных | Тип | Расположение | Изменения в ET-014 |
|-----------------------------------|----------------|----------------------------------------------|-------------------------------------------------|
| OSM-vector (`trails`) | существующий | `/app/data/centralfederal.sqlite` | **нет** |
| Личные GPX треки (ET-006) | существующий | браузер (memory) | **нет** |
| Публичные GPS треки (ET-008) | существующий | `/app/data/gps_tracks.sqlite` | **нет** |
| OSRM-граф | существующий | `/app/data/enduro.osrm.*` | **нет** |
| Terrain hillshade/TRI/hypso PNG | существующий | `data/terrain/*` | **нет** |
| User UI state | существующий | `localStorage` | **нет** новых ключей, нет миграции |
| MapLibre client tile cache | существующий | браузер (LRU MapLibre) | **нет** |
| Серверный кэш | не предусмотрен | n/a | **нет** |
| DOM-state `#terrain-popup` | runtime UI | браузер (DOM) | **меняется**: `display:none` при `openSheet()` |
| DOM-state `#terrain-toggle` | runtime UI | браузер (DOM) | **меняется**: класс `.active` снимается |
| DOM-state `.bottom-sheet` | runtime UI | браузер (DOM) | **не меняется** (та же логика `.open`) |
| DOM-state `#sheet-backdrop` | runtime UI | браузер (DOM) | **не меняется** (та же логика `.visible`) |
| `closeTerrainOnOutside` listener | runtime UI | браузер (event listener на `document`) | **снимается** через `removeEventListener` |
## 3. Серверные данные
### 3.1 БД
**Без изменений vs ET-013/ET-008.**
- `centralfederal.sqlite` — read-only для ET-014.
- `gps_tracks.sqlite` — read-only для ET-014.
- Никаких ALTER/CREATE/INSERT/UPDATE/DELETE.
- Никаких миграций.
### 3.2 Тайлы на диске
**Без изменений.** `data/terrain/*`, `data/osm/*`, `data/osrm/*` — не
трогаются.
### 3.3 Статика `src/web/`
| Файл | Изменение |
|-----------------------|-----------------------------------------------------------------|
| `src/web/app.js` | +1 helper-функция `closeTerrainPopup()` (~7 строк), +1 вызов в `openSheet()` |
| `src/web/app.css` | **нет** |
| `src/web/index.html` | **нет** |
| `src/web/gps_tracks.js` | **нет** |
| `src/web/gpx.js` | **нет** |
| `src/web/units.js` | **нет** |
| `src/web/style.json` | **нет** |
| `src/web/style-dark.json` | **нет** |
Дельта размера `app.js`: ~+300 байт (helper-функция + комментарий +
вызов). Пренебрежимо.
## 4. Клиентские данные
### 4.1 localStorage
**Без изменений.** Используются существующие ключи (read-only для
ET-014):
| Ключ | Назначение | Изменения в ET-014 |
|----------------------------|---------------------------------------------|--------------------|
| `terrain-hillshade` | `'1' | '0'` — чекбокс «Тени рельефа» | **нет** |
| `terrain-tri` | `'1' | '0'` — чекбокс «Перепады» | **нет** |
| `gps-tracks-enabled` | публичные треки on/off | **нет** |
| `gps-filter-*` | состояние фильтров публичных треков | **нет** |
| `theme` | `'dark' | 'light'` | **нет** |
| `units` | `'km' | 'mi'` | **нет** |
| `base-layer` | подложка | **нет** |
Никакой миграции. Существующие сессии при следующей загрузке
автоматически получают исправленное UI-поведение.
### 4.2 MapLibre LRU (browser-side)
Без изменений. Тайловый кэш не задействован — мы не меняем тайлы,
zoom-уровни, source.minzoom, или paint properties.
### 4.3 DOM runtime state
Ниже — единственное место, где ET-014 «меняет данные» (в runtime
браузера, не на диске):
#### `#terrain-popup`
- **До ET-014**: при клике на `#public-tracks-filters-btn` popup
остаётся `display: block`, z=500.
- **После ET-014**: при любом `openSheet(id)`, если
`popup.style.display !== 'none'`, popup переключается в
`display: none`.
#### `#terrain-toggle`
- **До ET-014**: при открытии sheet'а сохраняет класс `.active`.
- **После ET-014**: при `openSheet(id)` класс `.active` снимается
(синхронно с popup'ом).
#### Event listener `closeTerrainOnOutside` на `document`
- **До ET-014**: добавлен в `toggleTerrainPopup()` через
`addEventListener('click', closeTerrainOnOutside)`. Удаляется в двух
местах: повторный клик по `#terrain-toggle` и срабатывание самого
`closeTerrainOnOutside`.
- **После ET-014**: дополнительно удаляется внутри
`closeTerrainPopup()`, который вызывается из `openSheet()`. Двойной
`removeEventListener` безвреден (DOM-спека: removeEventListener на
отсутствующий listener — no-op).
### 4.4 In-memory constants
**Нет.** Никаких новых JS-констант (в отличие от ET-013 с
`HILLSHADE_PAINT` / `TRI_PAINT`). Только новая функция и вызов.
## 5. Контракты API
### 5.1 Backend endpoints
**Без изменений.** ET-014 — чистый клиент. Никаких новых вызовов,
никакого изменения параметров запросов, никакого изменения частоты
запросов.
| Endpoint | До ET-014 | После ET-014 |
|-----------------------------------------|-------------|--------------|
| `GET /api/gps-tracks/tiles/{z}/{x}/{y}.mvt` | без изменений | без изменений |
| `GET /api/gps-tracks?bbox=…` | без изменений | без изменений |
| `GET /api/gps-tracks/{id}/download` | без изменений | без изменений |
| `GET /api/gps-tracks/health` | без изменений | без изменений |
| `GET /terrain/{layer}/{z}/{x}/{y}.png` | без изменений | без изменений |
| `GET /api/route/*` | без изменений | без изменений |
| `GET /api/trails/*` | без изменений | без изменений |
### 5.2 Frontend internal API (`src/web/app.js`)
| Функция | До ET-014 | После ET-014 |
|-------------------------------|-------------------------------------------------|------------------------------------------------------------------------------|
| `openSheet(id)` | публичный (вызывается из всех `toggle*Sheet`) | публичный, контракт сохранён; добавлен внутренний вызов `closeTerrainPopup()` |
| `closeSheet(id)` | публичный | без изменений |
| `closeAllSheets()` | публичный | без изменений |
| `toggleTerrainPopup()` | публичный | без изменений |
| `closeTerrainOnOutside(e)` | публичный (выставляется как event handler) | без изменений (опциональный TD-1 рефакторинг описан в ADR-019) |
| `closeTerrainPopup()` | **отсутствует** | **новая** publish-функция (для возможного reuse) |
Контракт `openSheet(id)` совместим со всеми существующими вызовами:
```bash
$ grep -n 'openSheet(' src/web/*.js
```
- `app.js:openSheet(...)` — собственная реализация.
- `app.js:openSheet('sheet-route')`, `openSheet('sheet-recon')`,
`openSheet('sheet-scenic')`, `openSheet('sheet-link')`,
`openSheet('sheet-gpx')` — все продолжают работать как раньше.
- `gps_tracks.js:openSheet('sheet-gps-filters')` — продолжает работать;
дополнительно теперь корректно закрывает popup.
## 6. Миграции
**Нет.** Никаких миграций БД, миграций localStorage, миграций конфигов.
При деплое в test:
- `data/*` — без изменений.
- БД — без изменений.
- localStorage — старые ключи интерпретируются как раньше.
- MapLibre LRU — самоочищается при reload браузера; явной инвал. не нужно.
## 7. Тестовые данные
### 7.1 Для unit-тестов
В ET-014 **новых python unit-тестов не добавляется** — поведение
исключительно UI и тестируется через Playwright.
Опционально (cleanup, не обязательно): тест на статический grep по
`src/web/app.js`, что:
- Есть функция `closeTerrainPopup`.
- В теле `openSheet` есть вызов `closeTerrainPopup()`.
Если такой тест добавляется, формат — как `test_terrain_paint.py` в
ET-013 (`tests/unit/test_ui_z_index_fix.py`, regex по исходнику без
JS-runtime). Это **не блокирующий гейт** ET-014.
### 7.2 Для integration-тестов
Не применимо. ET-014 не трогает API endpoints, integration-тесты не нужны.
### 7.3 Для UI-тестов (Playwright)
`04b-ui-test-cases.md` — TC-UI-01..TC-UI-08:
- Запускается на test-среде `https://openclaw.mva154.duckdns.org/enduro/`.
- Данные — реальные (БД, тайлы) на mva154.
- Скриншоты в `tests/e2e/__screenshots__/ET-014/`.
- Не пиксельный diff; визуальная приёмка оператором + DOM-assertion'ы
(`classList.contains('open')`, `elementFromPoint`,
`getBoundingClientRect`).
## 8. Резервные копии и DR
**Без изменений.** ET-014 не пишет данных. RPO = 0.
## 9. Privacy / Compliance
| Аспект | Требование |
|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| PII | **Нет.** ET-014 не собирает, не обрабатывает, не передаёт никаких данных |
| Licensing | Не применимо |
| Attribution | MapLibre attribution control — без изменений |
| GDPR / 152-ФЗ | Не применимо |
## 10. Связанные документы
- `01-brd.md` §1 (бизнес-контекст), §3 (бизнес-цель), §4 (BR-01..BR-06)
- `02-trz.md` §1.1 (DOM-структура), §1.2 (стек z-index), §1.3 (корень),
§2 (REQ-F, REQ-NF), §3 (варианты)
- `03-acceptance-criteria.md` AC-01..AC-14
- `04b-ui-test-cases.md` TC-UI-01..TC-UI-08
- `06-adr/ADR-019-terrain-popup-yields-to-sheet.md`
- `07-infra-requirements.md`
- `10-tech-risks.md`
- `docs/work-items/ET-013/08-data-requirements.md` — образец «read-only
data» документа (наследие)
- `docs/work-items/ET-012/08-data-requirements.md` — образец «read-pattern
change» документа (наследие)